mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-09 23:00:21 +00:00
fix 1 mysterious divide error
fix 3 NULL dereference bugs in writeback tracing, on SD card removal w/o umount -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJPNI/ZAAoJECvKgwp+S8JaXNsP/3UwYM4R/bIqjsGSEr8mpxzs L/9hq85Vql+HDIZ0QT2Zj8aYcF2iYhjxrrVGVjNmINY3bSvniqtrZ6oCejdj7wqR vb2ECC3csUnvUbbewCOM4EaowU2CoANhO5xZeDzOu9SnYfMPuxRzjFlxU5WehJm1 5dKcCtbaO9Bleo5aZyr2AAaZPgE2lG7Hrvk8HghPhEw7ZBtO1Pc3iVegEhIvRiZR tUNTCwxE7QV1GehTUTgGpJWNL4qzrbyiqm/Vg+yI27l13IPn6mb/qfe7eHDFUTCb Ey6oeojhmmv0Kgc7b38/0U6q1QNL8x+zJP3J21wMmYqn2DtkLgZkI4TAcmBZwwHi rGvrwQESzTpiuhdXxQEOQpmrd8IvTmiFQK+IZzJ3uUA197ROdxyWLmdbbMZvsLym 8rtC+WNR0IJmPmnWNl1pj2df8YmtWkAGLaw2RMj4RFz3AcXBRurAOrCVG8Lk8ptH pFS0n4W3ScuTrZFy1jXYjpVumeIAuWJ/ScPJZhVsDJmssZWv4ZNr/X+OExq0z3dJ g9IBJ64q1zJiD5gSs2+iXmBTEHP6lpap9hY9WjApep7RuDsM9+o78oVEJcGdXbRM StFJoFdyOrsIR0cuo4yd+Lp/1ZpqP2ES++itW2PA96RXAuP/4R040xXqK/qMEczW XfCHqpOIqpCF7lxt9bcc =shjO -----END PGP SIGNATURE----- Merge tag 'writeback-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/wfg/linux fix 1 mysterious divide error fix 3 NULL dereference bugs in writeback tracing, on SD card removal w/o umount * tag 'writeback-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/wfg/linux: writeback: fix dereferencing NULL bdi->dev on trace_writeback_queue lib: proportion: lower PROP_MAX_SHIFT to 32 on 64-bit kernel writeback: fix NULL bdi->dev in trace writeback_single_inode backing-dev: fix wakeup timer races with bdi_unregister()
This commit is contained in:
commit
af5feae3d7
@ -52,14 +52,6 @@ struct wb_writeback_work {
|
||||
struct completion *done; /* set if the caller waits */
|
||||
};
|
||||
|
||||
/*
|
||||
* Include the creation of the trace points after defining the
|
||||
* wb_writeback_work structure so that the definition remains local to this
|
||||
* file.
|
||||
*/
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/writeback.h>
|
||||
|
||||
/*
|
||||
* We don't actually have pdflush, but this one is exported though /proc...
|
||||
*/
|
||||
@ -92,6 +84,14 @@ static inline struct inode *wb_inode(struct list_head *head)
|
||||
return list_entry(head, struct inode, i_wb_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Include the creation of the trace points after defining the
|
||||
* wb_writeback_work structure and inline functions so that the definition
|
||||
* remains local to this file.
|
||||
*/
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/writeback.h>
|
||||
|
||||
/* Wakeup flusher thread or forker thread to fork it. Requires bdi->wb_lock. */
|
||||
static void bdi_wakeup_flusher(struct backing_dev_info *bdi)
|
||||
{
|
||||
|
@ -81,7 +81,11 @@ void prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl)
|
||||
* Limit the time part in order to ensure there are some bits left for the
|
||||
* cycle counter and fraction multiply.
|
||||
*/
|
||||
#if BITS_PER_LONG == 32
|
||||
#define PROP_MAX_SHIFT (3*BITS_PER_LONG/4)
|
||||
#else
|
||||
#define PROP_MAX_SHIFT (BITS_PER_LONG/2)
|
||||
#endif
|
||||
|
||||
#define PROP_FRAC_SHIFT (BITS_PER_LONG - PROP_MAX_SHIFT - 1)
|
||||
#define PROP_FRAC_BASE (1UL << PROP_FRAC_SHIFT)
|
||||
|
@ -47,7 +47,10 @@ DECLARE_EVENT_CLASS(writeback_work_class,
|
||||
__field(int, reason)
|
||||
),
|
||||
TP_fast_assign(
|
||||
strncpy(__entry->name, dev_name(bdi->dev), 32);
|
||||
struct device *dev = bdi->dev;
|
||||
if (!dev)
|
||||
dev = default_backing_dev_info.dev;
|
||||
strncpy(__entry->name, dev_name(dev), 32);
|
||||
__entry->nr_pages = work->nr_pages;
|
||||
__entry->sb_dev = work->sb ? work->sb->s_dev : 0;
|
||||
__entry->sync_mode = work->sync_mode;
|
||||
@ -426,7 +429,7 @@ DECLARE_EVENT_CLASS(writeback_single_inode_template,
|
||||
|
||||
TP_fast_assign(
|
||||
strncpy(__entry->name,
|
||||
dev_name(inode->i_mapping->backing_dev_info->dev), 32);
|
||||
dev_name(inode_to_bdi(inode)->dev), 32);
|
||||
__entry->ino = inode->i_ino;
|
||||
__entry->state = inode->i_state;
|
||||
__entry->dirtied_when = inode->dirtied_when;
|
||||
|
@ -318,7 +318,7 @@ static void wakeup_timer_fn(unsigned long data)
|
||||
if (bdi->wb.task) {
|
||||
trace_writeback_wake_thread(bdi);
|
||||
wake_up_process(bdi->wb.task);
|
||||
} else {
|
||||
} else if (bdi->dev) {
|
||||
/*
|
||||
* When bdi tasks are inactive for long time, they are killed.
|
||||
* In this case we have to wake-up the forker thread which
|
||||
@ -584,6 +584,8 @@ EXPORT_SYMBOL(bdi_register_dev);
|
||||
*/
|
||||
static void bdi_wb_shutdown(struct backing_dev_info *bdi)
|
||||
{
|
||||
struct task_struct *task;
|
||||
|
||||
if (!bdi_cap_writeback_dirty(bdi))
|
||||
return;
|
||||
|
||||
@ -602,8 +604,13 @@ static void bdi_wb_shutdown(struct backing_dev_info *bdi)
|
||||
* Finally, kill the kernel thread. We don't need to be RCU
|
||||
* safe anymore, since the bdi is gone from visibility.
|
||||
*/
|
||||
if (bdi->wb.task)
|
||||
kthread_stop(bdi->wb.task);
|
||||
spin_lock_bh(&bdi->wb_lock);
|
||||
task = bdi->wb.task;
|
||||
bdi->wb.task = NULL;
|
||||
spin_unlock_bh(&bdi->wb_lock);
|
||||
|
||||
if (task)
|
||||
kthread_stop(task);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -623,7 +630,9 @@ static void bdi_prune_sb(struct backing_dev_info *bdi)
|
||||
|
||||
void bdi_unregister(struct backing_dev_info *bdi)
|
||||
{
|
||||
if (bdi->dev) {
|
||||
struct device *dev = bdi->dev;
|
||||
|
||||
if (dev) {
|
||||
bdi_set_min_ratio(bdi, 0);
|
||||
trace_writeback_bdi_unregister(bdi);
|
||||
bdi_prune_sb(bdi);
|
||||
@ -632,8 +641,12 @@ void bdi_unregister(struct backing_dev_info *bdi)
|
||||
if (!bdi_cap_flush_forker(bdi))
|
||||
bdi_wb_shutdown(bdi);
|
||||
bdi_debug_unregister(bdi);
|
||||
device_unregister(bdi->dev);
|
||||
|
||||
spin_lock_bh(&bdi->wb_lock);
|
||||
bdi->dev = NULL;
|
||||
spin_unlock_bh(&bdi->wb_lock);
|
||||
|
||||
device_unregister(dev);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(bdi_unregister);
|
||||
|
Loading…
x
Reference in New Issue
Block a user