Explicitly pass in whether sb is pinned or not
fix famous Kees Cook bug, patches are scheduled for 2.6.35-rc1 and will go into stable. this is the first that fixes original issue. svn path=/dists/trunk/linux-2.6/; revision=15747
This commit is contained in:
parent
1567b0b483
commit
e61f224150
|
@ -20,6 +20,7 @@ linux-2.6 (2.6.34-1~experimental.1) UNRELEASED; urgency=low
|
|||
* Fix backlight support on some recent Thinkpads.
|
||||
* Enable autosuspend on UVC by default.
|
||||
* acpi: Fall back to manually changing SCI_EN.
|
||||
* Explicitly pass in whether sb is pinned or not.
|
||||
|
||||
[ Ben Hutchings ]
|
||||
* Prepare debconf templates for translation (Closes: #576758)
|
||||
|
|
196
debian/patches/bugfix/all/fs-explicitly-pass-in-whether-sb-is-pinned-or-not.patch
vendored
Normal file
196
debian/patches/bugfix/all/fs-explicitly-pass-in-whether-sb-is-pinned-or-not.patch
vendored
Normal file
|
@ -0,0 +1,196 @@
|
|||
From: Jens Axboe <axboe@kernel.dk>
|
||||
Date: 2010-05-06 07:08:55
|
||||
Subject: Explicitly pass in whether sb is pinned or not
|
||||
|
||||
|
||||
Revision two of this patch. I got rid of WB_SYNC_NONE_PIN, since we should not
|
||||
further muddy the sync type and whether or not the sb is pinned. Instead lets
|
||||
add a specific flag for this.
|
||||
|
||||
BZ: 15906, Launchpad: 543617
|
||||
|
||||
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
|
||||
index 4b37f7c..c9ac9cb 100644
|
||||
--- a/fs/fs-writeback.c
|
||||
+++ b/fs/fs-writeback.c
|
||||
@@ -45,6 +45,7 @@ struct wb_writeback_args {
|
||||
int for_kupdate:1;
|
||||
int range_cyclic:1;
|
||||
int for_background:1;
|
||||
+ int sb_pinned:1;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -230,6 +231,11 @@ static void bdi_sync_writeback(struct backing_dev_info *bdi,
|
||||
.sync_mode = WB_SYNC_ALL,
|
||||
.nr_pages = LONG_MAX,
|
||||
.range_cyclic = 0,
|
||||
+ /*
|
||||
+ * Setting sb_pinned is not necessary for WB_SYNC_ALL, but
|
||||
+ * lets make it explicitly clear.
|
||||
+ */
|
||||
+ .sb_pinned = 1,
|
||||
};
|
||||
struct bdi_work work;
|
||||
|
||||
@@ -245,21 +251,23 @@ static void bdi_sync_writeback(struct backing_dev_info *bdi,
|
||||
* @bdi: the backing device to write from
|
||||
* @sb: write inodes from this super_block
|
||||
* @nr_pages: the number of pages to write
|
||||
+ * @sb_locked: caller already holds sb umount sem.
|
||||
*
|
||||
* Description:
|
||||
* This does WB_SYNC_NONE opportunistic writeback. The IO is only
|
||||
* started when this function returns, we make no guarentees on
|
||||
- * completion. Caller need not hold sb s_umount semaphore.
|
||||
+ * completion. Caller specifies whether sb umount sem is held already or not.
|
||||
*
|
||||
*/
|
||||
void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb,
|
||||
- long nr_pages)
|
||||
+ long nr_pages, int sb_locked)
|
||||
{
|
||||
struct wb_writeback_args args = {
|
||||
.sb = sb,
|
||||
.sync_mode = WB_SYNC_NONE,
|
||||
.nr_pages = nr_pages,
|
||||
.range_cyclic = 1,
|
||||
+ .sb_pinned = sb_locked,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -577,7 +585,7 @@ static enum sb_pin_state pin_sb_for_writeback(struct writeback_control *wbc,
|
||||
/*
|
||||
* Caller must already hold the ref for this
|
||||
*/
|
||||
- if (wbc->sync_mode == WB_SYNC_ALL) {
|
||||
+ if (wbc->sync_mode == WB_SYNC_ALL || wbc->sb_pinned) {
|
||||
WARN_ON(!rwsem_is_locked(&sb->s_umount));
|
||||
return SB_NOT_PINNED;
|
||||
}
|
||||
@@ -751,6 +759,7 @@ static long wb_writeback(struct bdi_writeback *wb,
|
||||
.for_kupdate = args->for_kupdate,
|
||||
.for_background = args->for_background,
|
||||
.range_cyclic = args->range_cyclic,
|
||||
+ .sb_pinned = args->sb_pinned,
|
||||
};
|
||||
unsigned long oldest_jif;
|
||||
long wrote = 0;
|
||||
@@ -1183,6 +1192,18 @@ static void wait_sb_inodes(struct super_block *sb)
|
||||
iput(old_inode);
|
||||
}
|
||||
|
||||
+static void __writeback_inodes_sb(struct super_block *sb, int sb_locked)
|
||||
+{
|
||||
+ unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY);
|
||||
+ unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS);
|
||||
+ long nr_to_write;
|
||||
+
|
||||
+ nr_to_write = nr_dirty + nr_unstable +
|
||||
+ (inodes_stat.nr_inodes - inodes_stat.nr_unused);
|
||||
+
|
||||
+ bdi_start_writeback(sb->s_bdi, sb, nr_to_write, sb_locked);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* writeback_inodes_sb - writeback dirty inodes from given super_block
|
||||
* @sb: the superblock
|
||||
@@ -1194,18 +1215,23 @@ static void wait_sb_inodes(struct super_block *sb)
|
||||
*/
|
||||
void writeback_inodes_sb(struct super_block *sb)
|
||||
{
|
||||
- unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY);
|
||||
- unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS);
|
||||
- long nr_to_write;
|
||||
-
|
||||
- nr_to_write = nr_dirty + nr_unstable +
|
||||
- (inodes_stat.nr_inodes - inodes_stat.nr_unused);
|
||||
-
|
||||
- bdi_start_writeback(sb->s_bdi, sb, nr_to_write);
|
||||
+ __writeback_inodes_sb(sb, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(writeback_inodes_sb);
|
||||
|
||||
/**
|
||||
+ * writeback_inodes_sb_locked - writeback dirty inodes from given super_block
|
||||
+ * @sb: the superblock
|
||||
+ *
|
||||
+ * Like writeback_inodes_sb(), except the caller already holds the
|
||||
+ * sb umount sem.
|
||||
+ */
|
||||
+void writeback_inodes_sb_locked(struct super_block *sb)
|
||||
+{
|
||||
+ __writeback_inodes_sb(sb, 1);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
* writeback_inodes_sb_if_idle - start writeback if none underway
|
||||
* @sb: the superblock
|
||||
*
|
||||
diff --git a/fs/sync.c b/fs/sync.c
|
||||
index 92b2281..de6a441 100644
|
||||
--- a/fs/sync.c
|
||||
+++ b/fs/sync.c
|
||||
@@ -42,7 +42,7 @@ static int __sync_filesystem(struct super_block *sb, int wait)
|
||||
if (wait)
|
||||
sync_inodes_sb(sb);
|
||||
else
|
||||
- writeback_inodes_sb(sb);
|
||||
+ writeback_inodes_sb_locked(sb);
|
||||
|
||||
if (sb->s_op->sync_fs)
|
||||
sb->s_op->sync_fs(sb, wait);
|
||||
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
|
||||
index bd0e3c6..90e677a 100644
|
||||
--- a/include/linux/backing-dev.h
|
||||
+++ b/include/linux/backing-dev.h
|
||||
@@ -103,7 +103,7 @@ int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
|
||||
void bdi_unregister(struct backing_dev_info *bdi);
|
||||
int bdi_setup_and_register(struct backing_dev_info *, char *, unsigned int);
|
||||
void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb,
|
||||
- long nr_pages);
|
||||
+ long nr_pages, int sb_locked);
|
||||
int bdi_writeback_task(struct bdi_writeback *wb);
|
||||
int bdi_has_dirty_io(struct backing_dev_info *bdi);
|
||||
|
||||
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
|
||||
index 36520de..3790165 100644
|
||||
--- a/include/linux/writeback.h
|
||||
+++ b/include/linux/writeback.h
|
||||
@@ -65,6 +65,15 @@ struct writeback_control {
|
||||
* so we use a single control to update them
|
||||
*/
|
||||
unsigned no_nrwrite_index_update:1;
|
||||
+
|
||||
+ /*
|
||||
+ * For WB_SYNC_ALL, the sb must always be pinned. For WB_SYNC_NONE,
|
||||
+ * the writeback code will pin the sb for the caller. However,
|
||||
+ * for eg umount, the caller does WB_SYNC_NONE but already has
|
||||
+ * the sb pinned. If the below is set, caller already has the
|
||||
+ * sb pinned.
|
||||
+ */
|
||||
+ unsigned sb_pinned:1;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -73,6 +82,7 @@ struct writeback_control {
|
||||
struct bdi_writeback;
|
||||
int inode_wait(void *);
|
||||
void writeback_inodes_sb(struct super_block *);
|
||||
+void writeback_inodes_sb_locked(struct super_block *);
|
||||
int writeback_inodes_sb_if_idle(struct super_block *);
|
||||
void sync_inodes_sb(struct super_block *);
|
||||
void writeback_inodes_wbc(struct writeback_control *wbc);
|
||||
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
|
||||
index 0b19943..49d3508 100644
|
||||
--- a/mm/page-writeback.c
|
||||
+++ b/mm/page-writeback.c
|
||||
@@ -597,7 +597,7 @@ static void balance_dirty_pages(struct address_space *mapping,
|
||||
(!laptop_mode && ((global_page_state(NR_FILE_DIRTY)
|
||||
+ global_page_state(NR_UNSTABLE_NFS))
|
||||
> background_thresh)))
|
||||
- bdi_start_writeback(bdi, NULL, 0);
|
||||
+ bdi_start_writeback(bdi, NULL, 0, 0);
|
||||
}
|
||||
|
||||
void set_page_dirty_balance(struct page *page, int page_mkwrite)
|
|
@ -68,3 +68,4 @@
|
|||
+ bugfix/all/thinkpad-acpi-fix-backlight.patch
|
||||
+ bugfix/all/linux-2.6-usb-uvc-autosuspend.diff
|
||||
+ bugfix/all/linux-2.6-acpi-sleep-live-sci-live.patch
|
||||
+ bugfix/all/fs-explicitly-pass-in-whether-sb-is-pinned-or-not.patch
|
||||
|
|
Loading…
Reference in New Issue