diff options
Diffstat (limited to 'fs/gfs2/lops.c')
| -rw-r--r-- | fs/gfs2/lops.c | 470 |
1 files changed, 235 insertions, 235 deletions
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 3b395c41b2f3..6c27cea761c6 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
| @@ -27,7 +27,104 @@ | |||
| 27 | #include "trans.h" | 27 | #include "trans.h" |
| 28 | #include "util.h" | 28 | #include "util.h" |
| 29 | 29 | ||
| 30 | static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | 30 | /** |
| 31 | * gfs2_pin - Pin a buffer in memory | ||
| 32 | * @sdp: The superblock | ||
| 33 | * @bh: The buffer to be pinned | ||
| 34 | * | ||
| 35 | * The log lock must be held when calling this function | ||
| 36 | */ | ||
| 37 | static void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh) | ||
| 38 | { | ||
| 39 | struct gfs2_bufdata *bd; | ||
| 40 | |||
| 41 | gfs2_assert_withdraw(sdp, test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)); | ||
| 42 | |||
| 43 | clear_buffer_dirty(bh); | ||
| 44 | if (test_set_buffer_pinned(bh)) | ||
| 45 | gfs2_assert_withdraw(sdp, 0); | ||
| 46 | if (!buffer_uptodate(bh)) | ||
| 47 | gfs2_io_error_bh(sdp, bh); | ||
| 48 | bd = bh->b_private; | ||
| 49 | /* If this buffer is in the AIL and it has already been written | ||
| 50 | * to in-place disk block, remove it from the AIL. | ||
| 51 | */ | ||
| 52 | if (bd->bd_ail) | ||
| 53 | list_move(&bd->bd_ail_st_list, &bd->bd_ail->ai_ail2_list); | ||
| 54 | get_bh(bh); | ||
| 55 | } | ||
| 56 | |||
| 57 | /** | ||
| 58 | * gfs2_unpin - Unpin a buffer | ||
| 59 | * @sdp: the filesystem the buffer belongs to | ||
| 60 | * @bh: The buffer to unpin | ||
| 61 | * @ai: | ||
| 62 | * | ||
| 63 | */ | ||
| 64 | |||
| 65 | static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, | ||
| 66 | struct gfs2_ail *ai) | ||
| 67 | { | ||
| 68 | struct gfs2_bufdata *bd = bh->b_private; | ||
| 69 | |||
| 70 | gfs2_assert_withdraw(sdp, buffer_uptodate(bh)); | ||
| 71 | |||
| 72 | if (!buffer_pinned(bh)) | ||
| 73 | gfs2_assert_withdraw(sdp, 0); | ||
| 74 | |||
| 75 | lock_buffer(bh); | ||
| 76 | mark_buffer_dirty(bh); | ||
| 77 | clear_buffer_pinned(bh); | ||
| 78 | |||
| 79 | gfs2_log_lock(sdp); | ||
| 80 | if (bd->bd_ail) { | ||
| 81 | list_del(&bd->bd_ail_st_list); | ||
| 82 | brelse(bh); | ||
| 83 | } else { | ||
| 84 | struct gfs2_glock *gl = bd->bd_gl; | ||
| 85 | list_add(&bd->bd_ail_gl_list, &gl->gl_ail_list); | ||
| 86 | atomic_inc(&gl->gl_ail_count); | ||
| 87 | } | ||
| 88 | bd->bd_ail = ai; | ||
| 89 | list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list); | ||
| 90 | gfs2_log_unlock(sdp); | ||
| 91 | unlock_buffer(bh); | ||
| 92 | } | ||
| 93 | |||
| 94 | |||
| 95 | static inline struct gfs2_log_descriptor *bh_log_desc(struct buffer_head *bh) | ||
| 96 | { | ||
| 97 | return (struct gfs2_log_descriptor *)bh->b_data; | ||
| 98 | } | ||
| 99 | |||
| 100 | static inline __be64 *bh_log_ptr(struct buffer_head *bh) | ||
| 101 | { | ||
| 102 | struct gfs2_log_descriptor *ld = bh_log_desc(bh); | ||
| 103 | return (__force __be64 *)(ld + 1); | ||
| 104 | } | ||
| 105 | |||
| 106 | static inline __be64 *bh_ptr_end(struct buffer_head *bh) | ||
| 107 | { | ||
| 108 | return (__force __be64 *)(bh->b_data + bh->b_size); | ||
| 109 | } | ||
| 110 | |||
| 111 | |||
| 112 | static struct buffer_head *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type) | ||
| 113 | { | ||
| 114 | struct buffer_head *bh = gfs2_log_get_buf(sdp); | ||
| 115 | struct gfs2_log_descriptor *ld = bh_log_desc(bh); | ||
| 116 | ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | ||
| 117 | ld->ld_header.mh_type = cpu_to_be32(GFS2_METATYPE_LD); | ||
| 118 | ld->ld_header.mh_format = cpu_to_be32(GFS2_FORMAT_LD); | ||
| 119 | ld->ld_type = cpu_to_be32(ld_type); | ||
| 120 | ld->ld_length = 0; | ||
| 121 | ld->ld_data1 = 0; | ||
| 122 | ld->ld_data2 = 0; | ||
| 123 | memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved)); | ||
| 124 | return bh; | ||
| 125 | } | ||
| 126 | |||
| 127 | static void __glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | ||
| 31 | { | 128 | { |
| 32 | struct gfs2_glock *gl; | 129 | struct gfs2_glock *gl; |
| 33 | struct gfs2_trans *tr = current->journal_info; | 130 | struct gfs2_trans *tr = current->journal_info; |
| @@ -38,15 +135,19 @@ static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
| 38 | if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl))) | 135 | if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl))) |
| 39 | return; | 136 | return; |
| 40 | 137 | ||
| 41 | gfs2_log_lock(sdp); | 138 | if (!list_empty(&le->le_list)) |
| 42 | if (!list_empty(&le->le_list)){ | ||
| 43 | gfs2_log_unlock(sdp); | ||
| 44 | return; | 139 | return; |
| 45 | } | 140 | |
| 46 | gfs2_glock_hold(gl); | 141 | gfs2_glock_hold(gl); |
| 47 | set_bit(GLF_DIRTY, &gl->gl_flags); | 142 | set_bit(GLF_DIRTY, &gl->gl_flags); |
| 48 | sdp->sd_log_num_gl++; | 143 | sdp->sd_log_num_gl++; |
| 49 | list_add(&le->le_list, &sdp->sd_log_le_gl); | 144 | list_add(&le->le_list, &sdp->sd_log_le_gl); |
| 145 | } | ||
| 146 | |||
| 147 | static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | ||
| 148 | { | ||
| 149 | gfs2_log_lock(sdp); | ||
| 150 | __glock_lo_add(sdp, le); | ||
| 50 | gfs2_log_unlock(sdp); | 151 | gfs2_log_unlock(sdp); |
| 51 | } | 152 | } |
| 52 | 153 | ||
| @@ -71,30 +172,25 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
| 71 | struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le); | 172 | struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le); |
| 72 | struct gfs2_trans *tr; | 173 | struct gfs2_trans *tr; |
| 73 | 174 | ||
| 175 | lock_buffer(bd->bd_bh); | ||
| 74 | gfs2_log_lock(sdp); | 176 | gfs2_log_lock(sdp); |
| 75 | if (!list_empty(&bd->bd_list_tr)) { | 177 | if (!list_empty(&bd->bd_list_tr)) |
| 76 | gfs2_log_unlock(sdp); | 178 | goto out; |
| 77 | return; | ||
| 78 | } | ||
| 79 | tr = current->journal_info; | 179 | tr = current->journal_info; |
| 80 | tr->tr_touched = 1; | 180 | tr->tr_touched = 1; |
| 81 | tr->tr_num_buf++; | 181 | tr->tr_num_buf++; |
| 82 | list_add(&bd->bd_list_tr, &tr->tr_list_buf); | 182 | list_add(&bd->bd_list_tr, &tr->tr_list_buf); |
| 83 | gfs2_log_unlock(sdp); | ||
| 84 | |||
| 85 | if (!list_empty(&le->le_list)) | 183 | if (!list_empty(&le->le_list)) |
| 86 | return; | 184 | goto out; |
| 87 | 185 | __glock_lo_add(sdp, &bd->bd_gl->gl_le); | |
| 88 | gfs2_trans_add_gl(bd->bd_gl); | ||
| 89 | |||
| 90 | gfs2_meta_check(sdp, bd->bd_bh); | 186 | gfs2_meta_check(sdp, bd->bd_bh); |
| 91 | gfs2_pin(sdp, bd->bd_bh); | 187 | gfs2_pin(sdp, bd->bd_bh); |
| 92 | gfs2_log_lock(sdp); | ||
| 93 | sdp->sd_log_num_buf++; | 188 | sdp->sd_log_num_buf++; |
| 94 | list_add(&le->le_list, &sdp->sd_log_le_buf); | 189 | list_add(&le->le_list, &sdp->sd_log_le_buf); |
| 95 | gfs2_log_unlock(sdp); | ||
| 96 | |||
| 97 | tr->tr_num_buf_new++; | 190 | tr->tr_num_buf_new++; |
| 191 | out: | ||
| 192 | gfs2_log_unlock(sdp); | ||
| 193 | unlock_buffer(bd->bd_bh); | ||
| 98 | } | 194 | } |
| 99 | 195 | ||
| 100 | static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | 196 | static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
| @@ -117,8 +213,7 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp) | |||
| 117 | struct buffer_head *bh; | 213 | struct buffer_head *bh; |
| 118 | struct gfs2_log_descriptor *ld; | 214 | struct gfs2_log_descriptor *ld; |
| 119 | struct gfs2_bufdata *bd1 = NULL, *bd2; | 215 | struct gfs2_bufdata *bd1 = NULL, *bd2; |
| 120 | unsigned int total = sdp->sd_log_num_buf; | 216 | unsigned int total; |
| 121 | unsigned int offset = BUF_OFFSET; | ||
| 122 | unsigned int limit; | 217 | unsigned int limit; |
| 123 | unsigned int num; | 218 | unsigned int num; |
| 124 | unsigned n; | 219 | unsigned n; |
| @@ -127,22 +222,20 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp) | |||
| 127 | limit = buf_limit(sdp); | 222 | limit = buf_limit(sdp); |
| 128 | /* for 4k blocks, limit = 503 */ | 223 | /* for 4k blocks, limit = 503 */ |
| 129 | 224 | ||
| 225 | gfs2_log_lock(sdp); | ||
| 226 | total = sdp->sd_log_num_buf; | ||
| 130 | bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list); | 227 | bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list); |
| 131 | while(total) { | 228 | while(total) { |
| 132 | num = total; | 229 | num = total; |
| 133 | if (total > limit) | 230 | if (total > limit) |
| 134 | num = limit; | 231 | num = limit; |
| 135 | bh = gfs2_log_get_buf(sdp); | 232 | gfs2_log_unlock(sdp); |
| 136 | ld = (struct gfs2_log_descriptor *)bh->b_data; | 233 | bh = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_METADATA); |
| 137 | ptr = (__be64 *)(bh->b_data + offset); | 234 | gfs2_log_lock(sdp); |
| 138 | ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | 235 | ld = bh_log_desc(bh); |
| 139 | ld->ld_header.mh_type = cpu_to_be32(GFS2_METATYPE_LD); | 236 | ptr = bh_log_ptr(bh); |
| 140 | ld->ld_header.mh_format = cpu_to_be32(GFS2_FORMAT_LD); | ||
| 141 | ld->ld_type = cpu_to_be32(GFS2_LOG_DESC_METADATA); | ||
| 142 | ld->ld_length = cpu_to_be32(num + 1); | 237 | ld->ld_length = cpu_to_be32(num + 1); |
| 143 | ld->ld_data1 = cpu_to_be32(num); | 238 | ld->ld_data1 = cpu_to_be32(num); |
| 144 | ld->ld_data2 = cpu_to_be32(0); | ||
| 145 | memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved)); | ||
| 146 | 239 | ||
| 147 | n = 0; | 240 | n = 0; |
| 148 | list_for_each_entry_continue(bd1, &sdp->sd_log_le_buf, | 241 | list_for_each_entry_continue(bd1, &sdp->sd_log_le_buf, |
| @@ -152,21 +245,27 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp) | |||
| 152 | break; | 245 | break; |
| 153 | } | 246 | } |
| 154 | 247 | ||
| 155 | set_buffer_dirty(bh); | 248 | gfs2_log_unlock(sdp); |
| 156 | ll_rw_block(WRITE, 1, &bh); | 249 | submit_bh(WRITE, bh); |
| 250 | gfs2_log_lock(sdp); | ||
| 157 | 251 | ||
| 158 | n = 0; | 252 | n = 0; |
| 159 | list_for_each_entry_continue(bd2, &sdp->sd_log_le_buf, | 253 | list_for_each_entry_continue(bd2, &sdp->sd_log_le_buf, |
| 160 | bd_le.le_list) { | 254 | bd_le.le_list) { |
| 255 | get_bh(bd2->bd_bh); | ||
| 256 | gfs2_log_unlock(sdp); | ||
| 257 | lock_buffer(bd2->bd_bh); | ||
| 161 | bh = gfs2_log_fake_buf(sdp, bd2->bd_bh); | 258 | bh = gfs2_log_fake_buf(sdp, bd2->bd_bh); |
| 162 | set_buffer_dirty(bh); | 259 | submit_bh(WRITE, bh); |
| 163 | ll_rw_block(WRITE, 1, &bh); | 260 | gfs2_log_lock(sdp); |
| 164 | if (++n >= num) | 261 | if (++n >= num) |
| 165 | break; | 262 | break; |
| 166 | } | 263 | } |
| 167 | 264 | ||
| 265 | BUG_ON(total < num); | ||
| 168 | total -= num; | 266 | total -= num; |
| 169 | } | 267 | } |
| 268 | gfs2_log_unlock(sdp); | ||
| 170 | } | 269 | } |
| 171 | 270 | ||
| 172 | static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | 271 | static void buf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) |
| @@ -270,11 +369,8 @@ static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
| 270 | tr = current->journal_info; | 369 | tr = current->journal_info; |
| 271 | tr->tr_touched = 1; | 370 | tr->tr_touched = 1; |
| 272 | tr->tr_num_revoke++; | 371 | tr->tr_num_revoke++; |
| 273 | |||
| 274 | gfs2_log_lock(sdp); | ||
| 275 | sdp->sd_log_num_revoke++; | 372 | sdp->sd_log_num_revoke++; |
| 276 | list_add(&le->le_list, &sdp->sd_log_le_revoke); | 373 | list_add(&le->le_list, &sdp->sd_log_le_revoke); |
| 277 | gfs2_log_unlock(sdp); | ||
| 278 | } | 374 | } |
| 279 | 375 | ||
| 280 | static void revoke_lo_before_commit(struct gfs2_sbd *sdp) | 376 | static void revoke_lo_before_commit(struct gfs2_sbd *sdp) |
| @@ -284,32 +380,25 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) | |||
| 284 | struct buffer_head *bh; | 380 | struct buffer_head *bh; |
| 285 | unsigned int offset; | 381 | unsigned int offset; |
| 286 | struct list_head *head = &sdp->sd_log_le_revoke; | 382 | struct list_head *head = &sdp->sd_log_le_revoke; |
| 287 | struct gfs2_revoke *rv; | 383 | struct gfs2_bufdata *bd; |
| 288 | 384 | ||
| 289 | if (!sdp->sd_log_num_revoke) | 385 | if (!sdp->sd_log_num_revoke) |
| 290 | return; | 386 | return; |
| 291 | 387 | ||
| 292 | bh = gfs2_log_get_buf(sdp); | 388 | bh = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_REVOKE); |
| 293 | ld = (struct gfs2_log_descriptor *)bh->b_data; | 389 | ld = bh_log_desc(bh); |
| 294 | ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC); | ||
| 295 | ld->ld_header.mh_type = cpu_to_be32(GFS2_METATYPE_LD); | ||
| 296 | ld->ld_header.mh_format = cpu_to_be32(GFS2_FORMAT_LD); | ||
| 297 | ld->ld_type = cpu_to_be32(GFS2_LOG_DESC_REVOKE); | ||
| 298 | ld->ld_length = cpu_to_be32(gfs2_struct2blk(sdp, sdp->sd_log_num_revoke, | 390 | ld->ld_length = cpu_to_be32(gfs2_struct2blk(sdp, sdp->sd_log_num_revoke, |
| 299 | sizeof(u64))); | 391 | sizeof(u64))); |
| 300 | ld->ld_data1 = cpu_to_be32(sdp->sd_log_num_revoke); | 392 | ld->ld_data1 = cpu_to_be32(sdp->sd_log_num_revoke); |
| 301 | ld->ld_data2 = cpu_to_be32(0); | ||
| 302 | memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved)); | ||
| 303 | offset = sizeof(struct gfs2_log_descriptor); | 393 | offset = sizeof(struct gfs2_log_descriptor); |
| 304 | 394 | ||
| 305 | while (!list_empty(head)) { | 395 | while (!list_empty(head)) { |
| 306 | rv = list_entry(head->next, struct gfs2_revoke, rv_le.le_list); | 396 | bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list); |
| 307 | list_del_init(&rv->rv_le.le_list); | 397 | list_del_init(&bd->bd_le.le_list); |
| 308 | sdp->sd_log_num_revoke--; | 398 | sdp->sd_log_num_revoke--; |
| 309 | 399 | ||
| 310 | if (offset + sizeof(u64) > sdp->sd_sb.sb_bsize) { | 400 | if (offset + sizeof(u64) > sdp->sd_sb.sb_bsize) { |
| 311 | set_buffer_dirty(bh); | 401 | submit_bh(WRITE, bh); |
| 312 | ll_rw_block(WRITE, 1, &bh); | ||
| 313 | 402 | ||
| 314 | bh = gfs2_log_get_buf(sdp); | 403 | bh = gfs2_log_get_buf(sdp); |
| 315 | mh = (struct gfs2_meta_header *)bh->b_data; | 404 | mh = (struct gfs2_meta_header *)bh->b_data; |
| @@ -319,15 +408,14 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) | |||
| 319 | offset = sizeof(struct gfs2_meta_header); | 408 | offset = sizeof(struct gfs2_meta_header); |
| 320 | } | 409 | } |
| 321 | 410 | ||
| 322 | *(__be64 *)(bh->b_data + offset) = cpu_to_be64(rv->rv_blkno); | 411 | *(__be64 *)(bh->b_data + offset) = cpu_to_be64(bd->bd_blkno); |
| 323 | kfree(rv); | 412 | kmem_cache_free(gfs2_bufdata_cachep, bd); |
| 324 | 413 | ||
| 325 | offset += sizeof(u64); | 414 | offset += sizeof(u64); |
| 326 | } | 415 | } |
| 327 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); | 416 | gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); |
| 328 | 417 | ||
| 329 | set_buffer_dirty(bh); | 418 | submit_bh(WRITE, bh); |
| 330 | ll_rw_block(WRITE, 1, &bh); | ||
| 331 | } | 419 | } |
| 332 | 420 | ||
| 333 | static void revoke_lo_before_scan(struct gfs2_jdesc *jd, | 421 | static void revoke_lo_before_scan(struct gfs2_jdesc *jd, |
| @@ -466,222 +554,136 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
| 466 | struct address_space *mapping = bd->bd_bh->b_page->mapping; | 554 | struct address_space *mapping = bd->bd_bh->b_page->mapping; |
| 467 | struct gfs2_inode *ip = GFS2_I(mapping->host); | 555 | struct gfs2_inode *ip = GFS2_I(mapping->host); |
| 468 | 556 | ||
| 557 | lock_buffer(bd->bd_bh); | ||
| 469 | gfs2_log_lock(sdp); | 558 | gfs2_log_lock(sdp); |
| 470 | if (!list_empty(&bd->bd_list_tr)) { | 559 | if (!list_empty(&bd->bd_list_tr)) |
| 471 | gfs2_log_unlock(sdp); | 560 | goto out; |
| 472 | return; | ||
| 473 | } | ||
| 474 | tr->tr_touched = 1; | 561 | tr->tr_touched = 1; |
| 475 | if (gfs2_is_jdata(ip)) { | 562 | if (gfs2_is_jdata(ip)) { |
| 476 | tr->tr_num_buf++; | 563 | tr->tr_num_buf++; |
| 477 | list_add(&bd->bd_list_tr, &tr->tr_list_buf); | 564 | list_add(&bd->bd_list_tr, &tr->tr_list_buf); |
| 478 | } | 565 | } |
| 479 | gfs2_log_unlock(sdp); | ||
| 480 | if (!list_empty(&le->le_list)) | 566 | if (!list_empty(&le->le_list)) |
| 481 | return; | 567 | goto out; |
| 482 | 568 | ||
| 483 | gfs2_trans_add_gl(bd->bd_gl); | 569 | __glock_lo_add(sdp, &bd->bd_gl->gl_le); |
| 484 | if (gfs2_is_jdata(ip)) { | 570 | if (gfs2_is_jdata(ip)) { |
| 485 | sdp->sd_log_num_jdata++; | ||
| 486 | gfs2_pin(sdp, bd->bd_bh); | 571 | gfs2_pin(sdp, bd->bd_bh); |
| 487 | tr->tr_num_databuf_new++; | 572 | tr->tr_num_databuf_new++; |
| 573 | sdp->sd_log_num_databuf++; | ||
| 574 | list_add(&le->le_list, &sdp->sd_log_le_databuf); | ||
| 575 | } else { | ||
| 576 | list_add(&le->le_list, &sdp->sd_log_le_ordered); | ||
| 488 | } | 577 | } |
| 489 | gfs2_log_lock(sdp); | 578 | out: |
| 490 | sdp->sd_log_num_databuf++; | ||
| 491 | list_add(&le->le_list, &sdp->sd_log_le_databuf); | ||
| 492 | gfs2_log_unlock(sdp); | 579 | gfs2_log_unlock(sdp); |
| 580 | unlock_buffer(bd->bd_bh); | ||
| 493 | } | 581 | } |
| 494 | 582 | ||
| 495 | static int gfs2_check_magic(struct buffer_head *bh) | 583 | static void gfs2_check_magic(struct buffer_head *bh) |
| 496 | { | 584 | { |
| 497 | struct page *page = bh->b_page; | ||
| 498 | void *kaddr; | 585 | void *kaddr; |
| 499 | __be32 *ptr; | 586 | __be32 *ptr; |
| 500 | int rv = 0; | ||
| 501 | 587 | ||
| 502 | kaddr = kmap_atomic(page, KM_USER0); | 588 | clear_buffer_escaped(bh); |
| 589 | kaddr = kmap_atomic(bh->b_page, KM_USER0); | ||
| 503 | ptr = kaddr + bh_offset(bh); | 590 | ptr = kaddr + bh_offset(bh); |
| 504 | if (*ptr == cpu_to_be32(GFS2_MAGIC)) | 591 | if (*ptr == cpu_to_be32(GFS2_MAGIC)) |
| 505 | rv = 1; | 592 | set_buffer_escaped(bh); |
| 506 | kunmap_atomic(kaddr, KM_USER0); | 593 | kunmap_atomic(kaddr, KM_USER0); |
| 507 | |||
| 508 | return rv; | ||
| 509 | } | 594 | } |
| 510 | 595 | ||
| 511 | /** | 596 | static void gfs2_write_blocks(struct gfs2_sbd *sdp, struct buffer_head *bh, |
| 512 | * databuf_lo_before_commit - Scan the data buffers, writing as we go | 597 | struct list_head *list, struct list_head *done, |
| 513 | * | 598 | unsigned int n) |
| 514 | * Here we scan through the lists of buffers and make the assumption | ||
| 515 | * that any buffer thats been pinned is being journaled, and that | ||
| 516 | * any unpinned buffer is an ordered write data buffer and therefore | ||
| 517 | * will be written back rather than journaled. | ||
| 518 | */ | ||
| 519 | static void databuf_lo_before_commit(struct gfs2_sbd *sdp) | ||
| 520 | { | 599 | { |
| 521 | LIST_HEAD(started); | 600 | struct buffer_head *bh1; |
| 522 | struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt; | ||
| 523 | struct buffer_head *bh = NULL,*bh1 = NULL; | ||
| 524 | struct gfs2_log_descriptor *ld; | 601 | struct gfs2_log_descriptor *ld; |
| 525 | unsigned int limit; | 602 | struct gfs2_bufdata *bd; |
| 526 | unsigned int total_dbuf; | 603 | __be64 *ptr; |
| 527 | unsigned int total_jdata = sdp->sd_log_num_jdata; | 604 | |
| 528 | unsigned int num, n; | 605 | if (!bh) |
| 529 | __be64 *ptr = NULL; | 606 | return; |
| 530 | 607 | ||
| 531 | limit = databuf_limit(sdp); | 608 | ld = bh_log_desc(bh); |
| 609 | ld->ld_length = cpu_to_be32(n + 1); | ||
| 610 | ld->ld_data1 = cpu_to_be32(n); | ||
| 532 | 611 | ||
| 533 | /* | 612 | ptr = bh_log_ptr(bh); |
| 534 | * Start writing ordered buffers, write journaled buffers | 613 | |
| 535 | * into the log along with a header | 614 | get_bh(bh); |
| 536 | */ | 615 | submit_bh(WRITE, bh); |
| 537 | gfs2_log_lock(sdp); | 616 | gfs2_log_lock(sdp); |
| 538 | total_dbuf = sdp->sd_log_num_databuf; | 617 | while(!list_empty(list)) { |
| 539 | bd2 = bd1 = list_prepare_entry(bd1, &sdp->sd_log_le_databuf, | 618 | bd = list_entry(list->next, struct gfs2_bufdata, bd_le.le_list); |
| 540 | bd_le.le_list); | 619 | list_move_tail(&bd->bd_le.le_list, done); |
| 541 | while(total_dbuf) { | 620 | get_bh(bd->bd_bh); |
| 542 | num = total_jdata; | 621 | while (be64_to_cpu(*ptr) != bd->bd_bh->b_blocknr) { |
| 543 | if (num > limit) | 622 | gfs2_log_incr_head(sdp); |
| 544 | num = limit; | 623 | ptr += 2; |
| 545 | n = 0; | ||
| 546 | list_for_each_entry_safe_continue(bd1, bdt, | ||
| 547 | &sdp->sd_log_le_databuf, | ||
| 548 | bd_le.le_list) { | ||
| 549 | /* store off the buffer head in a local ptr since | ||
| 550 | * gfs2_bufdata might change when we drop the log lock | ||
| 551 | */ | ||
| 552 | bh1 = bd1->bd_bh; | ||
| 553 | |||
| 554 | /* An ordered write buffer */ | ||
| 555 | if (bh1 && !buffer_pinned(bh1)) { | ||
| 556 | list_move(&bd1->bd_le.le_list, &started); | ||
| 557 | if (bd1 == bd2) { | ||
| 558 | bd2 = NULL; | ||
| 559 | bd2 = list_prepare_entry(bd2, | ||
| 560 | &sdp->sd_log_le_databuf, | ||
| 561 | bd_le.le_list); | ||
| 562 | } | ||
| 563 | total_dbuf--; | ||
| 564 | if (bh1) { | ||
| 565 | if (buffer_dirty(bh1)) { | ||
| 566 | get_bh(bh1); | ||
| 567 | |||
| 568 | gfs2_log_unlock(sdp); | ||
| 569 | |||
| 570 | ll_rw_block(SWRITE, 1, &bh1); | ||
| 571 | brelse(bh1); | ||
| 572 | |||
| 573 | gfs2_log_lock(sdp); | ||
| 574 | } | ||
| 575 | continue; | ||
| 576 | } | ||
| 577 | continue; | ||
| 578 | } else if (bh1) { /* A journaled buffer */ | ||
| 579 | int magic; | ||
| 580 | gfs2_log_unlock(sdp); | ||
| 581 | if (!bh) { | ||
| 582 | bh = gfs2_log_get_buf(sdp); | ||
| 583 | ld = (struct gfs2_log_descriptor *) | ||
| 584 | bh->b_data; | ||
| 585 | ptr = (__be64 *)(bh->b_data + | ||
| 586 | DATABUF_OFFSET); | ||
| 587 | ld->ld_header.mh_magic = | ||
| 588 | cpu_to_be32(GFS2_MAGIC); | ||
| 589 | ld->ld_header.mh_type = | ||
| 590 | cpu_to_be32(GFS2_METATYPE_LD); | ||
| 591 | ld->ld_header.mh_format = | ||
| 592 | cpu_to_be32(GFS2_FORMAT_LD); | ||
| 593 | ld->ld_type = | ||
| 594 | cpu_to_be32(GFS2_LOG_DESC_JDATA); | ||
| 595 | ld->ld_length = cpu_to_be32(num + 1); | ||
| 596 | ld->ld_data1 = cpu_to_be32(num); | ||
| 597 | ld->ld_data2 = cpu_to_be32(0); | ||
| 598 | memset(ld->ld_reserved, 0, sizeof(ld->ld_reserved)); | ||
| 599 | } | ||
| 600 | magic = gfs2_check_magic(bh1); | ||
| 601 | *ptr++ = cpu_to_be64(bh1->b_blocknr); | ||
| 602 | *ptr++ = cpu_to_be64((__u64)magic); | ||
| 603 | clear_buffer_escaped(bh1); | ||
| 604 | if (unlikely(magic != 0)) | ||
| 605 | set_buffer_escaped(bh1); | ||
| 606 | gfs2_log_lock(sdp); | ||
| 607 | if (++n >= num) | ||
| 608 | break; | ||
| 609 | } else if (!bh1) { | ||
| 610 | total_dbuf--; | ||
| 611 | sdp->sd_log_num_databuf--; | ||
| 612 | list_del_init(&bd1->bd_le.le_list); | ||
| 613 | if (bd1 == bd2) { | ||
| 614 | bd2 = NULL; | ||
| 615 | bd2 = list_prepare_entry(bd2, | ||
| 616 | &sdp->sd_log_le_databuf, | ||
| 617 | bd_le.le_list); | ||
| 618 | } | ||
| 619 | kmem_cache_free(gfs2_bufdata_cachep, bd1); | ||
| 620 | } | ||
| 621 | } | 624 | } |
| 622 | gfs2_log_unlock(sdp); | 625 | gfs2_log_unlock(sdp); |
| 623 | if (bh) { | 626 | lock_buffer(bd->bd_bh); |
| 624 | set_buffer_mapped(bh); | 627 | if (buffer_escaped(bd->bd_bh)) { |
| 625 | set_buffer_dirty(bh); | 628 | void *kaddr; |
| 626 | ll_rw_block(WRITE, 1, &bh); | 629 | bh1 = gfs2_log_get_buf(sdp); |
| 627 | bh = NULL; | 630 | kaddr = kmap_atomic(bd->bd_bh->b_page, KM_USER0); |
| 631 | memcpy(bh1->b_data, kaddr + bh_offset(bd->bd_bh), | ||
| 632 | bh1->b_size); | ||
| 633 | kunmap_atomic(kaddr, KM_USER0); | ||
| 634 | *(__be32 *)bh1->b_data = 0; | ||
| 635 | clear_buffer_escaped(bd->bd_bh); | ||
| 636 | unlock_buffer(bd->bd_bh); | ||
| 637 | brelse(bd->bd_bh); | ||
| 638 | } else { | ||
| 639 | bh1 = gfs2_log_fake_buf(sdp, bd->bd_bh); | ||
| 628 | } | 640 | } |
| 629 | n = 0; | 641 | submit_bh(WRITE, bh1); |
| 630 | gfs2_log_lock(sdp); | 642 | gfs2_log_lock(sdp); |
| 631 | list_for_each_entry_continue(bd2, &sdp->sd_log_le_databuf, | 643 | ptr += 2; |
| 632 | bd_le.le_list) { | ||
| 633 | if (!bd2->bd_bh) | ||
| 634 | continue; | ||
| 635 | /* copy buffer if it needs escaping */ | ||
| 636 | gfs2_log_unlock(sdp); | ||
| 637 | if (unlikely(buffer_escaped(bd2->bd_bh))) { | ||
| 638 | void *kaddr; | ||
| 639 | struct page *page = bd2->bd_bh->b_page; | ||
| 640 | bh = gfs2_log_get_buf(sdp); | ||
| 641 | kaddr = kmap_atomic(page, KM_USER0); | ||
| 642 | memcpy(bh->b_data, | ||
| 643 | kaddr + bh_offset(bd2->bd_bh), | ||
| 644 | sdp->sd_sb.sb_bsize); | ||
| 645 | kunmap_atomic(kaddr, KM_USER0); | ||
| 646 | *(__be32 *)bh->b_data = 0; | ||
| 647 | } else { | ||
| 648 | bh = gfs2_log_fake_buf(sdp, bd2->bd_bh); | ||
| 649 | } | ||
| 650 | set_buffer_dirty(bh); | ||
| 651 | ll_rw_block(WRITE, 1, &bh); | ||
| 652 | gfs2_log_lock(sdp); | ||
| 653 | if (++n >= num) | ||
| 654 | break; | ||
| 655 | } | ||
| 656 | bh = NULL; | ||
| 657 | BUG_ON(total_dbuf < num); | ||
| 658 | total_dbuf -= num; | ||
| 659 | total_jdata -= num; | ||
| 660 | } | 644 | } |
| 661 | gfs2_log_unlock(sdp); | 645 | gfs2_log_unlock(sdp); |
| 646 | brelse(bh); | ||
| 647 | } | ||
| 662 | 648 | ||
| 663 | /* Wait on all ordered buffers */ | 649 | /** |
| 664 | while (!list_empty(&started)) { | 650 | * databuf_lo_before_commit - Scan the data buffers, writing as we go |
| 665 | gfs2_log_lock(sdp); | 651 | * |
| 666 | bd1 = list_entry(started.next, struct gfs2_bufdata, | 652 | */ |
| 667 | bd_le.le_list); | ||
| 668 | list_del_init(&bd1->bd_le.le_list); | ||
| 669 | sdp->sd_log_num_databuf--; | ||
| 670 | bh = bd1->bd_bh; | ||
| 671 | if (bh) { | ||
| 672 | bh->b_private = NULL; | ||
| 673 | get_bh(bh); | ||
| 674 | gfs2_log_unlock(sdp); | ||
| 675 | wait_on_buffer(bh); | ||
| 676 | brelse(bh); | ||
| 677 | } else | ||
| 678 | gfs2_log_unlock(sdp); | ||
| 679 | 653 | ||
| 680 | kmem_cache_free(gfs2_bufdata_cachep, bd1); | 654 | static void databuf_lo_before_commit(struct gfs2_sbd *sdp) |
| 681 | } | 655 | { |
| 656 | struct gfs2_bufdata *bd = NULL; | ||
| 657 | struct buffer_head *bh = NULL; | ||
| 658 | unsigned int n = 0; | ||
| 659 | __be64 *ptr = NULL, *end = NULL; | ||
| 660 | LIST_HEAD(processed); | ||
| 661 | LIST_HEAD(in_progress); | ||
| 682 | 662 | ||
| 683 | /* We've removed all the ordered write bufs here, so only jdata left */ | 663 | gfs2_log_lock(sdp); |
| 684 | gfs2_assert_warn(sdp, sdp->sd_log_num_databuf == sdp->sd_log_num_jdata); | 664 | while (!list_empty(&sdp->sd_log_le_databuf)) { |
| 665 | if (ptr == end) { | ||
| 666 | gfs2_log_unlock(sdp); | ||
| 667 | gfs2_write_blocks(sdp, bh, &in_progress, &processed, n); | ||
| 668 | n = 0; | ||
| 669 | bh = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_JDATA); | ||
| 670 | ptr = bh_log_ptr(bh); | ||
| 671 | end = bh_ptr_end(bh) - 1; | ||
| 672 | gfs2_log_lock(sdp); | ||
| 673 | continue; | ||
| 674 | } | ||
| 675 | bd = list_entry(sdp->sd_log_le_databuf.next, struct gfs2_bufdata, bd_le.le_list); | ||
| 676 | list_move_tail(&bd->bd_le.le_list, &in_progress); | ||
| 677 | gfs2_check_magic(bd->bd_bh); | ||
| 678 | *ptr++ = cpu_to_be64(bd->bd_bh->b_blocknr); | ||
| 679 | *ptr++ = cpu_to_be64(buffer_escaped(bh) ? 1 : 0); | ||
| 680 | n++; | ||
| 681 | } | ||
| 682 | gfs2_log_unlock(sdp); | ||
| 683 | gfs2_write_blocks(sdp, bh, &in_progress, &processed, n); | ||
| 684 | gfs2_log_lock(sdp); | ||
| 685 | list_splice(&processed, &sdp->sd_log_le_databuf); | ||
| 686 | gfs2_log_unlock(sdp); | ||
| 685 | } | 687 | } |
| 686 | 688 | ||
| 687 | static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, | 689 | static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, |
| @@ -765,11 +767,9 @@ static void databuf_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_ail *ai) | |||
| 765 | bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list); | 767 | bd = list_entry(head->next, struct gfs2_bufdata, bd_le.le_list); |
| 766 | list_del_init(&bd->bd_le.le_list); | 768 | list_del_init(&bd->bd_le.le_list); |
| 767 | sdp->sd_log_num_databuf--; | 769 | sdp->sd_log_num_databuf--; |
| 768 | sdp->sd_log_num_jdata--; | ||
| 769 | gfs2_unpin(sdp, bd->bd_bh, ai); | 770 | gfs2_unpin(sdp, bd->bd_bh, ai); |
| 770 | } | 771 | } |
| 771 | gfs2_assert_warn(sdp, !sdp->sd_log_num_databuf); | 772 | gfs2_assert_warn(sdp, !sdp->sd_log_num_databuf); |
| 772 | gfs2_assert_warn(sdp, !sdp->sd_log_num_jdata); | ||
| 773 | } | 773 | } |
| 774 | 774 | ||
| 775 | 775 | ||
| @@ -817,10 +817,10 @@ const struct gfs2_log_operations gfs2_databuf_lops = { | |||
| 817 | 817 | ||
| 818 | const struct gfs2_log_operations *gfs2_log_ops[] = { | 818 | const struct gfs2_log_operations *gfs2_log_ops[] = { |
| 819 | &gfs2_glock_lops, | 819 | &gfs2_glock_lops, |
| 820 | &gfs2_databuf_lops, | ||
| 820 | &gfs2_buf_lops, | 821 | &gfs2_buf_lops, |
| 821 | &gfs2_revoke_lops, | ||
| 822 | &gfs2_rg_lops, | 822 | &gfs2_rg_lops, |
| 823 | &gfs2_databuf_lops, | 823 | &gfs2_revoke_lops, |
| 824 | NULL, | 824 | NULL, |
| 825 | }; | 825 | }; |
| 826 | 826 | ||
