diff options
-rw-r--r-- | fs/nilfs2/segment.c | 79 | ||||
-rw-r--r-- | fs/nilfs2/segment.h | 2 |
2 files changed, 40 insertions, 41 deletions
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index ab439a7ef2d8..fa4abfc22d33 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
@@ -2425,43 +2425,43 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, | |||
2425 | return err; | 2425 | return err; |
2426 | } | 2426 | } |
2427 | 2427 | ||
2428 | struct nilfs_segctor_req { | ||
2429 | int mode; | ||
2430 | __u32 seq_accepted; | ||
2431 | int sc_err; /* construction failure */ | ||
2432 | int sb_err; /* super block writeback failure */ | ||
2433 | }; | ||
2434 | |||
2435 | #define FLUSH_FILE_BIT (0x1) /* data file only */ | 2428 | #define FLUSH_FILE_BIT (0x1) /* data file only */ |
2436 | #define FLUSH_DAT_BIT (1 << NILFS_DAT_INO) /* DAT only */ | 2429 | #define FLUSH_DAT_BIT (1 << NILFS_DAT_INO) /* DAT only */ |
2437 | 2430 | ||
2438 | static void nilfs_segctor_accept(struct nilfs_sc_info *sci, | 2431 | /** |
2439 | struct nilfs_segctor_req *req) | 2432 | * nilfs_segctor_accept - record accepted sequence count of log-write requests |
2433 | * @sci: segment constructor object | ||
2434 | */ | ||
2435 | static void nilfs_segctor_accept(struct nilfs_sc_info *sci) | ||
2440 | { | 2436 | { |
2441 | req->sc_err = req->sb_err = 0; | ||
2442 | spin_lock(&sci->sc_state_lock); | 2437 | spin_lock(&sci->sc_state_lock); |
2443 | req->seq_accepted = sci->sc_seq_request; | 2438 | sci->sc_seq_accepted = sci->sc_seq_request; |
2444 | spin_unlock(&sci->sc_state_lock); | 2439 | spin_unlock(&sci->sc_state_lock); |
2445 | 2440 | ||
2446 | if (sci->sc_timer) | 2441 | if (sci->sc_timer) |
2447 | del_timer_sync(sci->sc_timer); | 2442 | del_timer_sync(sci->sc_timer); |
2448 | } | 2443 | } |
2449 | 2444 | ||
2450 | static void nilfs_segctor_notify(struct nilfs_sc_info *sci, | 2445 | /** |
2451 | struct nilfs_segctor_req *req) | 2446 | * nilfs_segctor_notify - notify the result of request to caller threads |
2447 | * @sci: segment constructor object | ||
2448 | * @mode: mode of log forming | ||
2449 | * @err: error code to be notified | ||
2450 | */ | ||
2451 | static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err) | ||
2452 | { | 2452 | { |
2453 | /* Clear requests (even when the construction failed) */ | 2453 | /* Clear requests (even when the construction failed) */ |
2454 | spin_lock(&sci->sc_state_lock); | 2454 | spin_lock(&sci->sc_state_lock); |
2455 | 2455 | ||
2456 | if (req->mode == SC_LSEG_SR) { | 2456 | if (mode == SC_LSEG_SR) { |
2457 | sci->sc_state &= ~NILFS_SEGCTOR_COMMIT; | 2457 | sci->sc_state &= ~NILFS_SEGCTOR_COMMIT; |
2458 | sci->sc_seq_done = req->seq_accepted; | 2458 | sci->sc_seq_done = sci->sc_seq_accepted; |
2459 | nilfs_segctor_wakeup(sci, req->sc_err ? : req->sb_err); | 2459 | nilfs_segctor_wakeup(sci, err); |
2460 | sci->sc_flush_request = 0; | 2460 | sci->sc_flush_request = 0; |
2461 | } else { | 2461 | } else { |
2462 | if (req->mode == SC_FLUSH_FILE) | 2462 | if (mode == SC_FLUSH_FILE) |
2463 | sci->sc_flush_request &= ~FLUSH_FILE_BIT; | 2463 | sci->sc_flush_request &= ~FLUSH_FILE_BIT; |
2464 | else if (req->mode == SC_FLUSH_DAT) | 2464 | else if (mode == SC_FLUSH_DAT) |
2465 | sci->sc_flush_request &= ~FLUSH_DAT_BIT; | 2465 | sci->sc_flush_request &= ~FLUSH_DAT_BIT; |
2466 | 2466 | ||
2467 | /* re-enable timer if checkpoint creation was not done */ | 2467 | /* re-enable timer if checkpoint creation was not done */ |
@@ -2472,30 +2472,37 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, | |||
2472 | spin_unlock(&sci->sc_state_lock); | 2472 | spin_unlock(&sci->sc_state_lock); |
2473 | } | 2473 | } |
2474 | 2474 | ||
2475 | static int nilfs_segctor_construct(struct nilfs_sc_info *sci, | 2475 | /** |
2476 | struct nilfs_segctor_req *req) | 2476 | * nilfs_segctor_construct - form logs and write them to disk |
2477 | * @sci: segment constructor object | ||
2478 | * @mode: mode of log forming | ||
2479 | */ | ||
2480 | static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode) | ||
2477 | { | 2481 | { |
2478 | struct nilfs_sb_info *sbi = sci->sc_sbi; | 2482 | struct nilfs_sb_info *sbi = sci->sc_sbi; |
2479 | struct the_nilfs *nilfs = sbi->s_nilfs; | 2483 | struct the_nilfs *nilfs = sbi->s_nilfs; |
2480 | int err = 0; | 2484 | int err = 0; |
2481 | 2485 | ||
2486 | nilfs_segctor_accept(sci); | ||
2487 | |||
2482 | if (nilfs_discontinued(nilfs)) | 2488 | if (nilfs_discontinued(nilfs)) |
2483 | req->mode = SC_LSEG_SR; | 2489 | mode = SC_LSEG_SR; |
2484 | if (!nilfs_segctor_confirm(sci)) { | 2490 | if (!nilfs_segctor_confirm(sci)) |
2485 | err = nilfs_segctor_do_construct(sci, req->mode); | 2491 | err = nilfs_segctor_do_construct(sci, mode); |
2486 | req->sc_err = err; | 2492 | |
2487 | } | ||
2488 | if (likely(!err)) { | 2493 | if (likely(!err)) { |
2489 | if (req->mode != SC_FLUSH_DAT) | 2494 | if (mode != SC_FLUSH_DAT) |
2490 | atomic_set(&nilfs->ns_ndirtyblks, 0); | 2495 | atomic_set(&nilfs->ns_ndirtyblks, 0); |
2491 | if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) && | 2496 | if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) && |
2492 | nilfs_discontinued(nilfs)) { | 2497 | nilfs_discontinued(nilfs)) { |
2493 | down_write(&nilfs->ns_sem); | 2498 | down_write(&nilfs->ns_sem); |
2494 | req->sb_err = nilfs_commit_super(sbi, | 2499 | err = nilfs_commit_super( |
2495 | nilfs_altsb_need_update(nilfs)); | 2500 | sbi, nilfs_altsb_need_update(nilfs)); |
2496 | up_write(&nilfs->ns_sem); | 2501 | up_write(&nilfs->ns_sem); |
2497 | } | 2502 | } |
2498 | } | 2503 | } |
2504 | |||
2505 | nilfs_segctor_notify(sci, mode, err); | ||
2499 | return err; | 2506 | return err; |
2500 | } | 2507 | } |
2501 | 2508 | ||
@@ -2526,7 +2533,6 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, | |||
2526 | struct nilfs_sc_info *sci = NILFS_SC(sbi); | 2533 | struct nilfs_sc_info *sci = NILFS_SC(sbi); |
2527 | struct the_nilfs *nilfs = sbi->s_nilfs; | 2534 | struct the_nilfs *nilfs = sbi->s_nilfs; |
2528 | struct nilfs_transaction_info ti; | 2535 | struct nilfs_transaction_info ti; |
2529 | struct nilfs_segctor_req req = { .mode = SC_LSEG_SR }; | ||
2530 | int err; | 2536 | int err; |
2531 | 2537 | ||
2532 | if (unlikely(!sci)) | 2538 | if (unlikely(!sci)) |
@@ -2547,10 +2553,8 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, | |||
2547 | list_splice_tail_init(&nilfs->ns_gc_inodes, &sci->sc_gc_inodes); | 2553 | list_splice_tail_init(&nilfs->ns_gc_inodes, &sci->sc_gc_inodes); |
2548 | 2554 | ||
2549 | for (;;) { | 2555 | for (;;) { |
2550 | nilfs_segctor_accept(sci, &req); | 2556 | err = nilfs_segctor_construct(sci, SC_LSEG_SR); |
2551 | err = nilfs_segctor_construct(sci, &req); | ||
2552 | nilfs_remove_written_gcinodes(nilfs, &sci->sc_gc_inodes); | 2557 | nilfs_remove_written_gcinodes(nilfs, &sci->sc_gc_inodes); |
2553 | nilfs_segctor_notify(sci, &req); | ||
2554 | 2558 | ||
2555 | if (likely(!err)) | 2559 | if (likely(!err)) |
2556 | break; | 2560 | break; |
@@ -2583,13 +2587,9 @@ static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode) | |||
2583 | { | 2587 | { |
2584 | struct nilfs_sb_info *sbi = sci->sc_sbi; | 2588 | struct nilfs_sb_info *sbi = sci->sc_sbi; |
2585 | struct nilfs_transaction_info ti; | 2589 | struct nilfs_transaction_info ti; |
2586 | struct nilfs_segctor_req req = { .mode = mode }; | ||
2587 | 2590 | ||
2588 | nilfs_transaction_lock(sbi, &ti, 0); | 2591 | nilfs_transaction_lock(sbi, &ti, 0); |
2589 | 2592 | nilfs_segctor_construct(sci, mode); | |
2590 | nilfs_segctor_accept(sci, &req); | ||
2591 | nilfs_segctor_construct(sci, &req); | ||
2592 | nilfs_segctor_notify(sci, &req); | ||
2593 | 2593 | ||
2594 | /* | 2594 | /* |
2595 | * Unclosed segment should be retried. We do this using sc_timer. | 2595 | * Unclosed segment should be retried. We do this using sc_timer. |
@@ -2807,12 +2807,9 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) | |||
2807 | do { | 2807 | do { |
2808 | struct nilfs_sb_info *sbi = sci->sc_sbi; | 2808 | struct nilfs_sb_info *sbi = sci->sc_sbi; |
2809 | struct nilfs_transaction_info ti; | 2809 | struct nilfs_transaction_info ti; |
2810 | struct nilfs_segctor_req req = { .mode = SC_LSEG_SR }; | ||
2811 | 2810 | ||
2812 | nilfs_transaction_lock(sbi, &ti, 0); | 2811 | nilfs_transaction_lock(sbi, &ti, 0); |
2813 | nilfs_segctor_accept(sci, &req); | 2812 | ret = nilfs_segctor_construct(sci, SC_LSEG_SR); |
2814 | ret = nilfs_segctor_construct(sci, &req); | ||
2815 | nilfs_segctor_notify(sci, &req); | ||
2816 | nilfs_transaction_unlock(sbi); | 2813 | nilfs_transaction_unlock(sbi); |
2817 | 2814 | ||
2818 | } while (ret && retrycount-- > 0); | 2815 | } while (ret && retrycount-- > 0); |
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index 3d3ab2f9864c..3155e0c7f415 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h | |||
@@ -116,6 +116,7 @@ struct nilfs_segsum_pointer { | |||
116 | * @sc_wait_daemon: Daemon wait queue | 116 | * @sc_wait_daemon: Daemon wait queue |
117 | * @sc_wait_task: Start/end wait queue to control segctord task | 117 | * @sc_wait_task: Start/end wait queue to control segctord task |
118 | * @sc_seq_request: Request counter | 118 | * @sc_seq_request: Request counter |
119 | * @sc_seq_accept: Accepted request count | ||
119 | * @sc_seq_done: Completion counter | 120 | * @sc_seq_done: Completion counter |
120 | * @sc_sync: Request of explicit sync operation | 121 | * @sc_sync: Request of explicit sync operation |
121 | * @sc_interval: Timeout value of background construction | 122 | * @sc_interval: Timeout value of background construction |
@@ -169,6 +170,7 @@ struct nilfs_sc_info { | |||
169 | wait_queue_head_t sc_wait_task; | 170 | wait_queue_head_t sc_wait_task; |
170 | 171 | ||
171 | __u32 sc_seq_request; | 172 | __u32 sc_seq_request; |
173 | __u32 sc_seq_accepted; | ||
172 | __u32 sc_seq_done; | 174 | __u32 sc_seq_done; |
173 | 175 | ||
174 | int sc_sync; | 176 | int sc_sync; |