diff --git a/block/bio.c b/block/bio.c index 31d6b9b3dc6ee89d682e23b65be2c9ddef7fcaeb..89c862a1c4337c79992b33bbe2e5f247d2594c5c 100644 --- a/block/bio.c +++ b/block/bio.c @@ -977,7 +977,10 @@ int submit_bio_wait(struct bio *bio) bio->bi_end_io = submit_bio_wait_endio; bio->bi_opf |= REQ_SYNC; submit_bio(bio); + + task_set_wait_res(TASK_WAIT_BIO, bio); wait_for_completion_io(&done); + task_clear_wait_res(); return blk_status_to_errno(bio->bi_status); } diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 524953bf0994d505f42b4fa442bef3afa427a9da..cfe3810bccfdad57d4ec37a7e7ed77ce51b524fc 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -960,7 +960,9 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, if (buffer_shadow(bh)) { JBUFFER_TRACE(jh, "on shadow: sleep"); jbd_unlock_bh_state(bh); + task_set_wait_res(TASK_WAIT_PAGE, bh->b_page); wait_on_bit_io(&bh->b_state, BH_Shadow, TASK_UNINTERRUPTIBLE); + task_clear_wait_res(); goto repeat; } diff --git a/fs/proc/base.c b/fs/proc/base.c index 3b9b726b1a6ca1810675f4dd25b88c9c08d56e77..92d822d320e99bdaa7d5360ca1107f499ea699b6 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -558,6 +558,15 @@ static int proc_oom_score(struct seq_file *m, struct pid_namespace *ns, return 0; } +static int proc_wait_res(struct seq_file *m, struct pid_namespace *ns, + struct pid *pid, struct task_struct *task) +{ + seq_printf(m, "%d %px %lu %lu\n", task->wait_res_type, task->wait_page, + task->wait_moment, jiffies); + + return 0; +} + struct limit_names { const char *name; const char *unit; @@ -3041,6 +3050,7 @@ static const struct pid_entry tgid_base_stuff[] = { #ifdef CONFIG_LIVEPATCH ONE("patch_state", S_IRUSR, proc_pid_patch_state), #endif + ONE("wait_res", S_IRUGO, proc_wait_res), }; static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx) @@ -3419,6 +3429,7 @@ static const struct pid_entry tid_base_stuff[] = { #ifdef CONFIG_LIVEPATCH ONE("patch_state", S_IRUSR, proc_pid_patch_state), #endif + ONE("wait_res", S_IRUGO, proc_wait_res), }; static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx) diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 96225a77c112e6d705a6dcbabc59e662750c6c4c..180d91f6a45b28222fccf9c9793ab7e6a8c8a09e 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -350,8 +350,11 @@ map_bh(struct buffer_head *bh, struct super_block *sb, sector_t block) static inline void wait_on_buffer(struct buffer_head *bh) { might_sleep(); - if (buffer_locked(bh)) + if (buffer_locked(bh)) { + task_set_wait_res(TASK_WAIT_PAGE, bh->b_page); __wait_on_buffer(bh); + task_clear_wait_res(); + } } static inline int trylock_buffer(struct buffer_head *bh) @@ -362,8 +365,11 @@ static inline int trylock_buffer(struct buffer_head *bh) static inline void lock_buffer(struct buffer_head *bh) { might_sleep(); - if (!trylock_buffer(bh)) + if (!trylock_buffer(bh)) { + task_set_wait_res(TASK_WAIT_PAGE, bh->b_page); __lock_buffer(bh); + task_clear_wait_res(); + } } static inline struct buffer_head *getblk_unmovable(struct block_device *bdev, diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index b1bd2186e6d2bdc9428580184f4baa0ae51ec287..40c87e5dd0c8eecfc4fcb4aeec47e1fc0f8fbfa4 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -479,8 +479,11 @@ static inline int trylock_page(struct page *page) static inline void lock_page(struct page *page) { might_sleep(); - if (!trylock_page(page)) + if (!trylock_page(page)) { + task_set_wait_res(TASK_WAIT_PAGE, page); __lock_page(page); + task_clear_wait_res(); + } } /* @@ -542,8 +545,11 @@ static inline int wait_on_page_locked_killable(struct page *page) */ static inline void wait_on_page_writeback(struct page *page) { - if (PageWriteback(page)) + if (PageWriteback(page)) { + task_set_wait_res(TASK_WAIT_PAGE, page); wait_on_page_bit(page, PG_writeback); + task_clear_wait_res(); + } } extern void end_page_writeback(struct page *page); diff --git a/include/linux/sched.h b/include/linux/sched.h index fe40353fa920216f0e26cfe116137f35f742adf2..dbd927399de8b7f0bb83a66f7996fc14f3cc0561 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1217,6 +1217,14 @@ struct task_struct { void *security; #endif + + int wait_res_type; + union { + struct page *wait_page; + struct bio *wait_bio; + }; + unsigned long wait_moment; + ALI_HOTFIX_RESERVE(1) ALI_HOTFIX_RESERVE(2) ALI_HOTFIX_RESERVE(3) @@ -1243,6 +1251,28 @@ struct task_struct { */ }; +enum { + TASK_WAIT_PAGE = 1, + TASK_WAIT_BIO, +}; + +static inline void task_set_wait_res(int type, void *res) +{ + if (type == TASK_WAIT_PAGE) + current->wait_page = (struct page *)res; + else if (type == TASK_WAIT_BIO) + current->wait_bio = (struct bio *)res; + + current->wait_res_type = type; + current->wait_moment = jiffies; +} + +static inline void task_clear_wait_res(void) +{ + current->wait_page = NULL; + current->wait_res_type = 0; +} + static inline struct pid *task_pid(struct task_struct *task) { return task->thread_pid;