diff options
| -rw-r--r-- | fs/buffer.c | 17 | ||||
| -rw-r--r-- | fs/jbd/commit.c | 49 | ||||
| -rw-r--r-- | fs/jbd2/commit.c | 39 | ||||
| -rw-r--r-- | fs/nilfs2/super.c | 28 | ||||
| -rw-r--r-- | include/linux/buffer_head.h | 3 |
5 files changed, 63 insertions, 73 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 50efa339e051..6c8ad977f3d4 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -2912,13 +2912,6 @@ int submit_bh(int rw, struct buffer_head * bh) | |||
| 2912 | BUG_ON(buffer_unwritten(bh)); | 2912 | BUG_ON(buffer_unwritten(bh)); |
| 2913 | 2913 | ||
| 2914 | /* | 2914 | /* |
| 2915 | * Mask in barrier bit for a write (could be either a WRITE or a | ||
| 2916 | * WRITE_SYNC | ||
| 2917 | */ | ||
| 2918 | if (buffer_ordered(bh) && (rw & WRITE)) | ||
| 2919 | rw |= WRITE_BARRIER; | ||
| 2920 | |||
| 2921 | /* | ||
| 2922 | * Only clear out a write error when rewriting | 2915 | * Only clear out a write error when rewriting |
| 2923 | */ | 2916 | */ |
| 2924 | if (test_set_buffer_req(bh) && (rw & WRITE)) | 2917 | if (test_set_buffer_req(bh) && (rw & WRITE)) |
| @@ -3021,7 +3014,7 @@ EXPORT_SYMBOL(ll_rw_block); | |||
| 3021 | * and then start new I/O and then wait upon it. The caller must have a ref on | 3014 | * and then start new I/O and then wait upon it. The caller must have a ref on |
| 3022 | * the buffer_head. | 3015 | * the buffer_head. |
| 3023 | */ | 3016 | */ |
| 3024 | int sync_dirty_buffer(struct buffer_head *bh) | 3017 | int __sync_dirty_buffer(struct buffer_head *bh, int rw) |
| 3025 | { | 3018 | { |
| 3026 | int ret = 0; | 3019 | int ret = 0; |
| 3027 | 3020 | ||
| @@ -3030,7 +3023,7 @@ int sync_dirty_buffer(struct buffer_head *bh) | |||
| 3030 | if (test_clear_buffer_dirty(bh)) { | 3023 | if (test_clear_buffer_dirty(bh)) { |
| 3031 | get_bh(bh); | 3024 | get_bh(bh); |
| 3032 | bh->b_end_io = end_buffer_write_sync; | 3025 | bh->b_end_io = end_buffer_write_sync; |
| 3033 | ret = submit_bh(WRITE_SYNC, bh); | 3026 | ret = submit_bh(rw, bh); |
| 3034 | wait_on_buffer(bh); | 3027 | wait_on_buffer(bh); |
| 3035 | if (buffer_eopnotsupp(bh)) { | 3028 | if (buffer_eopnotsupp(bh)) { |
| 3036 | clear_buffer_eopnotsupp(bh); | 3029 | clear_buffer_eopnotsupp(bh); |
| @@ -3043,6 +3036,12 @@ int sync_dirty_buffer(struct buffer_head *bh) | |||
| 3043 | } | 3036 | } |
| 3044 | return ret; | 3037 | return ret; |
| 3045 | } | 3038 | } |
| 3039 | EXPORT_SYMBOL(__sync_dirty_buffer); | ||
| 3040 | |||
| 3041 | int sync_dirty_buffer(struct buffer_head *bh) | ||
| 3042 | { | ||
| 3043 | return __sync_dirty_buffer(bh, WRITE_SYNC); | ||
| 3044 | } | ||
| 3046 | EXPORT_SYMBOL(sync_dirty_buffer); | 3045 | EXPORT_SYMBOL(sync_dirty_buffer); |
| 3047 | 3046 | ||
| 3048 | /* | 3047 | /* |
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 28a9ddaa0c49..95d8c11c929e 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c | |||
| @@ -119,7 +119,6 @@ static int journal_write_commit_record(journal_t *journal, | |||
| 119 | struct buffer_head *bh; | 119 | struct buffer_head *bh; |
| 120 | journal_header_t *header; | 120 | journal_header_t *header; |
| 121 | int ret; | 121 | int ret; |
| 122 | int barrier_done = 0; | ||
| 123 | 122 | ||
| 124 | if (is_journal_aborted(journal)) | 123 | if (is_journal_aborted(journal)) |
| 125 | return 0; | 124 | return 0; |
| @@ -137,34 +136,36 @@ static int journal_write_commit_record(journal_t *journal, | |||
| 137 | 136 | ||
| 138 | JBUFFER_TRACE(descriptor, "write commit block"); | 137 | JBUFFER_TRACE(descriptor, "write commit block"); |
| 139 | set_buffer_dirty(bh); | 138 | set_buffer_dirty(bh); |
| 139 | |||
| 140 | if (journal->j_flags & JFS_BARRIER) { | 140 | if (journal->j_flags & JFS_BARRIER) { |
| 141 | set_buffer_ordered(bh); | 141 | ret = __sync_dirty_buffer(bh, WRITE_SYNC | WRITE_BARRIER); |
| 142 | barrier_done = 1; | ||
| 143 | } | ||
| 144 | ret = sync_dirty_buffer(bh); | ||
| 145 | if (barrier_done) | ||
| 146 | clear_buffer_ordered(bh); | ||
| 147 | /* is it possible for another commit to fail at roughly | ||
| 148 | * the same time as this one? If so, we don't want to | ||
| 149 | * trust the barrier flag in the super, but instead want | ||
| 150 | * to remember if we sent a barrier request | ||
| 151 | */ | ||
| 152 | if (ret == -EOPNOTSUPP && barrier_done) { | ||
| 153 | char b[BDEVNAME_SIZE]; | ||
| 154 | 142 | ||
| 155 | printk(KERN_WARNING | 143 | /* |
| 156 | "JBD: barrier-based sync failed on %s - " | 144 | * Is it possible for another commit to fail at roughly |
| 157 | "disabling barriers\n", | 145 | * the same time as this one? If so, we don't want to |
| 158 | bdevname(journal->j_dev, b)); | 146 | * trust the barrier flag in the super, but instead want |
| 159 | spin_lock(&journal->j_state_lock); | 147 | * to remember if we sent a barrier request |
| 160 | journal->j_flags &= ~JFS_BARRIER; | 148 | */ |
| 161 | spin_unlock(&journal->j_state_lock); | 149 | if (ret == -EOPNOTSUPP) { |
| 150 | char b[BDEVNAME_SIZE]; | ||
| 162 | 151 | ||
| 163 | /* And try again, without the barrier */ | 152 | printk(KERN_WARNING |
| 164 | set_buffer_uptodate(bh); | 153 | "JBD: barrier-based sync failed on %s - " |
| 165 | set_buffer_dirty(bh); | 154 | "disabling barriers\n", |
| 155 | bdevname(journal->j_dev, b)); | ||
| 156 | spin_lock(&journal->j_state_lock); | ||
| 157 | journal->j_flags &= ~JFS_BARRIER; | ||
| 158 | spin_unlock(&journal->j_state_lock); | ||
| 159 | |||
| 160 | /* And try again, without the barrier */ | ||
| 161 | set_buffer_uptodate(bh); | ||
| 162 | set_buffer_dirty(bh); | ||
| 163 | ret = sync_dirty_buffer(bh); | ||
| 164 | } | ||
| 165 | } else { | ||
| 166 | ret = sync_dirty_buffer(bh); | 166 | ret = sync_dirty_buffer(bh); |
| 167 | } | 167 | } |
| 168 | |||
| 168 | put_bh(bh); /* One for getblk() */ | 169 | put_bh(bh); /* One for getblk() */ |
| 169 | journal_put_journal_head(descriptor); | 170 | journal_put_journal_head(descriptor); |
| 170 | 171 | ||
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index f52e5e8049f1..7c068c189d80 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
| @@ -101,7 +101,6 @@ static int journal_submit_commit_record(journal_t *journal, | |||
| 101 | struct commit_header *tmp; | 101 | struct commit_header *tmp; |
| 102 | struct buffer_head *bh; | 102 | struct buffer_head *bh; |
| 103 | int ret; | 103 | int ret; |
| 104 | int barrier_done = 0; | ||
| 105 | struct timespec now = current_kernel_time(); | 104 | struct timespec now = current_kernel_time(); |
| 106 | 105 | ||
| 107 | if (is_journal_aborted(journal)) | 106 | if (is_journal_aborted(journal)) |
| @@ -136,30 +135,22 @@ static int journal_submit_commit_record(journal_t *journal, | |||
| 136 | if (journal->j_flags & JBD2_BARRIER && | 135 | if (journal->j_flags & JBD2_BARRIER && |
| 137 | !JBD2_HAS_INCOMPAT_FEATURE(journal, | 136 | !JBD2_HAS_INCOMPAT_FEATURE(journal, |
| 138 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { | 137 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { |
| 139 | set_buffer_ordered(bh); | 138 | ret = submit_bh(WRITE_SYNC_PLUG | WRITE_BARRIER, bh); |
| 140 | barrier_done = 1; | 139 | if (ret == -EOPNOTSUPP) { |
| 141 | } | 140 | printk(KERN_WARNING |
| 142 | ret = submit_bh(WRITE_SYNC_PLUG, bh); | 141 | "JBD2: Disabling barriers on %s, " |
| 143 | if (barrier_done) | 142 | "not supported by device\n", journal->j_devname); |
| 144 | clear_buffer_ordered(bh); | 143 | write_lock(&journal->j_state_lock); |
| 145 | 144 | journal->j_flags &= ~JBD2_BARRIER; | |
| 146 | /* is it possible for another commit to fail at roughly | 145 | write_unlock(&journal->j_state_lock); |
| 147 | * the same time as this one? If so, we don't want to | ||
| 148 | * trust the barrier flag in the super, but instead want | ||
| 149 | * to remember if we sent a barrier request | ||
| 150 | */ | ||
| 151 | if (ret == -EOPNOTSUPP && barrier_done) { | ||
| 152 | printk(KERN_WARNING | ||
| 153 | "JBD2: Disabling barriers on %s, " | ||
| 154 | "not supported by device\n", journal->j_devname); | ||
| 155 | write_lock(&journal->j_state_lock); | ||
| 156 | journal->j_flags &= ~JBD2_BARRIER; | ||
| 157 | write_unlock(&journal->j_state_lock); | ||
| 158 | 146 | ||
| 159 | /* And try again, without the barrier */ | 147 | /* And try again, without the barrier */ |
| 160 | lock_buffer(bh); | 148 | lock_buffer(bh); |
| 161 | set_buffer_uptodate(bh); | 149 | set_buffer_uptodate(bh); |
| 162 | clear_buffer_dirty(bh); | 150 | clear_buffer_dirty(bh); |
| 151 | ret = submit_bh(WRITE_SYNC_PLUG, bh); | ||
| 152 | } | ||
| 153 | } else { | ||
| 163 | ret = submit_bh(WRITE_SYNC_PLUG, bh); | 154 | ret = submit_bh(WRITE_SYNC_PLUG, bh); |
| 164 | } | 155 | } |
| 165 | *cbh = bh; | 156 | *cbh = bh; |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 1fa86b9df73b..68345430fb48 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
| @@ -175,24 +175,24 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag) | |||
| 175 | { | 175 | { |
| 176 | struct the_nilfs *nilfs = sbi->s_nilfs; | 176 | struct the_nilfs *nilfs = sbi->s_nilfs; |
| 177 | int err; | 177 | int err; |
| 178 | int barrier_done = 0; | ||
| 179 | 178 | ||
| 180 | if (nilfs_test_opt(sbi, BARRIER)) { | ||
| 181 | set_buffer_ordered(nilfs->ns_sbh[0]); | ||
| 182 | barrier_done = 1; | ||
| 183 | } | ||
| 184 | retry: | 179 | retry: |
| 185 | set_buffer_dirty(nilfs->ns_sbh[0]); | 180 | set_buffer_dirty(nilfs->ns_sbh[0]); |
| 186 | err = sync_dirty_buffer(nilfs->ns_sbh[0]); | 181 | |
| 187 | if (err == -EOPNOTSUPP && barrier_done) { | 182 | if (nilfs_test_opt(sbi, BARRIER)) { |
| 188 | nilfs_warning(sbi->s_super, __func__, | 183 | err = __sync_dirty_buffer(nilfs->ns_sbh[0], |
| 189 | "barrier-based sync failed. " | 184 | WRITE_SYNC | WRITE_BARRIER); |
| 190 | "disabling barriers\n"); | 185 | if (err == -EOPNOTSUPP) { |
| 191 | nilfs_clear_opt(sbi, BARRIER); | 186 | nilfs_warning(sbi->s_super, __func__, |
| 192 | barrier_done = 0; | 187 | "barrier-based sync failed. " |
| 193 | clear_buffer_ordered(nilfs->ns_sbh[0]); | 188 | "disabling barriers\n"); |
| 194 | goto retry; | 189 | nilfs_clear_opt(sbi, BARRIER); |
| 190 | goto retry; | ||
| 191 | } | ||
| 192 | } else { | ||
| 193 | err = sync_dirty_buffer(nilfs->ns_sbh[0]); | ||
| 195 | } | 194 | } |
| 195 | |||
| 196 | if (unlikely(err)) { | 196 | if (unlikely(err)) { |
| 197 | printk(KERN_ERR | 197 | printk(KERN_ERR |
| 198 | "NILFS: unable to write superblock (err=%d)\n", err); | 198 | "NILFS: unable to write superblock (err=%d)\n", err); |
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 43e649a72529..72c1cf83eb85 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h | |||
| @@ -32,7 +32,6 @@ enum bh_state_bits { | |||
| 32 | BH_Delay, /* Buffer is not yet allocated on disk */ | 32 | BH_Delay, /* Buffer is not yet allocated on disk */ |
| 33 | BH_Boundary, /* Block is followed by a discontiguity */ | 33 | BH_Boundary, /* Block is followed by a discontiguity */ |
| 34 | BH_Write_EIO, /* I/O error on write */ | 34 | BH_Write_EIO, /* I/O error on write */ |
| 35 | BH_Ordered, /* ordered write */ | ||
| 36 | BH_Eopnotsupp, /* operation not supported (barrier) */ | 35 | BH_Eopnotsupp, /* operation not supported (barrier) */ |
| 37 | BH_Unwritten, /* Buffer is allocated on disk but not written */ | 36 | BH_Unwritten, /* Buffer is allocated on disk but not written */ |
| 38 | BH_Quiet, /* Buffer Error Prinks to be quiet */ | 37 | BH_Quiet, /* Buffer Error Prinks to be quiet */ |
| @@ -125,7 +124,6 @@ BUFFER_FNS(Async_Write, async_write) | |||
| 125 | BUFFER_FNS(Delay, delay) | 124 | BUFFER_FNS(Delay, delay) |
| 126 | BUFFER_FNS(Boundary, boundary) | 125 | BUFFER_FNS(Boundary, boundary) |
| 127 | BUFFER_FNS(Write_EIO, write_io_error) | 126 | BUFFER_FNS(Write_EIO, write_io_error) |
| 128 | BUFFER_FNS(Ordered, ordered) | ||
| 129 | BUFFER_FNS(Eopnotsupp, eopnotsupp) | 127 | BUFFER_FNS(Eopnotsupp, eopnotsupp) |
| 130 | BUFFER_FNS(Unwritten, unwritten) | 128 | BUFFER_FNS(Unwritten, unwritten) |
| 131 | 129 | ||
| @@ -183,6 +181,7 @@ void unlock_buffer(struct buffer_head *bh); | |||
| 183 | void __lock_buffer(struct buffer_head *bh); | 181 | void __lock_buffer(struct buffer_head *bh); |
| 184 | void ll_rw_block(int, int, struct buffer_head * bh[]); | 182 | void ll_rw_block(int, int, struct buffer_head * bh[]); |
| 185 | int sync_dirty_buffer(struct buffer_head *bh); | 183 | int sync_dirty_buffer(struct buffer_head *bh); |
| 184 | int __sync_dirty_buffer(struct buffer_head *bh, int rw); | ||
| 186 | int submit_bh(int, struct buffer_head *); | 185 | int submit_bh(int, struct buffer_head *); |
| 187 | void write_boundary_block(struct block_device *bdev, | 186 | void write_boundary_block(struct block_device *bdev, |
| 188 | sector_t bblock, unsigned blocksize); | 187 | sector_t bblock, unsigned blocksize); |
