Add wb_writeback_work->free_done, which is used to free the wb_completion variable when the reference count becomes zero. Signed-off-by: Julian Sun <sunjunchao@xxxxxxxxxxxxx> --- fs/fs-writeback.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 4a6c22df5649..56faf5c3d064 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -49,6 +49,7 @@ struct wb_writeback_work { unsigned int for_background:1; unsigned int for_sync:1; /* sync(2) WB_SYNC_ALL writeback */ unsigned int free_work:1; /* free work on completion */ + unsigned int free_done:1; /* free wb_completion on completion */ enum wb_reason reason; /* why was writeback initiated? */ struct list_head list; /* pending work list */ @@ -169,15 +170,19 @@ static void wb_wakeup_delayed(struct bdi_writeback *wb) static void finish_writeback_work(struct wb_writeback_work *work) { struct wb_completion *done = work->done; + bool free_done = work->free_done; if (work->free_work) kfree(work); if (done) { wait_queue_head_t *waitq = done->waitq; - /* @done can't be accessed after the following dec */ - if (atomic_dec_and_test(&done->cnt)) + /* @done can't be accessed after the following dec unless free_done is true */ + if (atomic_dec_and_test(&done->cnt)) { wake_up_all(waitq); + if (free_done) + kfree(done); + } } } -- 2.20.1