History

block: optionally snapshot page contents to provide stable pages during write

This provides a band-aid to provide stable page writes on jbd without needing to backport the fixed locking and page writeback bit handling schemes of jbd2. The band-aid works by using bounce buffers to snapshot page contents instead of waiting. For those wondering about the ext3 bandage -- fixing the jbd locking (which was done as part of ext4dev years ago) is a lot of surgery, and setting PG_writeback on data pages when we actually hold the page lock dropped ext3 performance by nearly an order of magnitude. If we're going to migrate iscsi and raid to use stable page writes, the complaints about high latency will likely return. We might as well centralize their page snapshotting thing to one place.

Darrick J. Wong committed 13 years ago

Commit ffecfd11 parent 13575ca7 files · +70 −13Browse files

Unified · Split

7 files
  1. arch/tile/Kconfig +0 −6
  2. block/blk-core.c +5 −3
  3. fs/ext3/super.c +1 −0
  4. include/uapi/linux/fs.h +3 −0
  5. mm/Kconfig +13 −0
  6. mm/bounce.c +44 −4
  7. mm/page-writeback.c +4 −0
arch/tile/Kconfig+0−6
@@ -412,12 +412,6 @@ config TILE_USB · 411 unmodified lines
412412 Provides USB host adapter support for the built-in EHCI and OHCI
413413 interfaces on TILE-Gx chips.
414414
415−# USB OHCI needs the bounce pool since tilegx will often have more
416−# than 4GB of memory, but we don't currently use the IOTLB to present
417−# a 32-bit address to OHCI. So we need to use a bounce pool instead.
418−config NEED_BOUNCE_POOL
419− def_bool USB_OHCI_HCD
420−
421415 source "drivers/pci/hotplug/Kconfig"
422416
423417 endmenu
block/blk-core.c+5−3
@@ -1474,6 +1474,11 @@ void blk_queue_bio(struct request_queue *q, struct bio *bio) · 1473 unmodified lines
14741474 */
14751475 blk_queue_bounce(q, &bio);
14761476
1477+ if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
1478+ bio_endio(bio, -EIO);
1479+ return;
1480+ }
1481+
14771482 if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
14781483 spin_lock_irq(q->queue_lock);
14791484 where = ELEVATOR_INSERT_FLUSH;
@@ -1714,9 +1719,6 @@ generic_make_request_checks(struct bio *bio) · 234 unmodified lines
17141719 */
17151720 blk_partition_remap(bio);
17161721
1717− if (bio_integrity_enabled(bio) && bio_integrity_prep(bio))
1718− goto end_io;
1719−
17201722 if (bio_check_eod(bio, nr_sectors))
17211723 goto end_io;
17221724
fs/ext3/super.c+1−0
@@ -2065,6 +2065,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) · 2064 unmodified lines
20652065 test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA ? "journal":
20662066 test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
20672067 "writeback");
2068+ sb->s_flags |= MS_SNAP_STABLE;
20682069
20692070 return 0;
20702071
include/uapi/linux/fs.h+3−0
@@ -86,6 +86,9 @@ struct inodes_stat_t { · 85 unmodified lines
8686 #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */
8787 #define MS_I_VERSION (1<<23) /* Update inode I_version field */
8888 #define MS_STRICTATIME (1<<24) /* Always perform atime updates */
89+
90+/* These sb flags are internal to the kernel */
91+#define MS_SNAP_STABLE (1<<27) /* Snapshot pages during writeback, if needed */
8992 #define MS_NOSEC (1<<28)
9093 #define MS_BORN (1<<29)
9194 #define MS_ACTIVE (1<<30)
mm/Kconfig+13−0
@@ -258,6 +258,19 @@ config BOUNCE · 257 unmodified lines
258258 def_bool y
259259 depends on BLOCK && MMU && (ZONE_DMA || HIGHMEM)
260260
261+# On the 'tile' arch, USB OHCI needs the bounce pool since tilegx will often
262+# have more than 4GB of memory, but we don't currently use the IOTLB to present
263+# a 32-bit address to OHCI. So we need to use a bounce pool instead.
264+#
265+# We also use the bounce pool to provide stable page writes for jbd. jbd
266+# initiates buffer writeback without locking the page or setting PG_writeback,
267+# and fixing that behavior (a second time; jbd2 doesn't have this problem) is
268+# a major rework effort. Instead, use the bounce buffer to snapshot pages
269+# (until jbd goes away). The only jbd user is ext3.
270+config NEED_BOUNCE_POOL
271+ bool
272+ default y if (TILE && USB_OHCI_HCD) || (BLK_DEV_INTEGRITY && JBD)
273+
261274 config NR_QUICK
262275 int
263276 depends on QUICKLIST
mm/bounce.c+44−4
@@ -178,8 +178,45 @@ static void bounce_end_io_read_isa(struct bio *bio, int err) · 177 unmodified lines
178178 __bounce_end_io_read(bio, isa_page_pool, err);
179179 }
180180
181+#ifdef CONFIG_NEED_BOUNCE_POOL
182+static int must_snapshot_stable_pages(struct request_queue *q, struct bio *bio)
183+{
184+ struct page *page;
185+ struct backing_dev_info *bdi;
186+ struct address_space *mapping;
187+ struct bio_vec *from;
188+ int i;
189+
190+ if (bio_data_dir(bio) != WRITE)
191+ return 0;
192+
193+ if (!bdi_cap_stable_pages_required(&q->backing_dev_info))
194+ return 0;
195+
196+ /*
197+ * Based on the first page that has a valid mapping, decide whether or
198+ * not we have to employ bounce buffering to guarantee stable pages.
199+ */
200+ bio_for_each_segment(from, bio, i) {
201+ page = from->bv_page;
202+ mapping = page_mapping(page);
203+ if (!mapping)
204+ continue;
205+ bdi = mapping->backing_dev_info;
206+ return mapping->host->i_sb->s_flags & MS_SNAP_STABLE;
207+ }
208+
209+ return 0;
210+}
211+#else
212+static int must_snapshot_stable_pages(struct request_queue *q, struct bio *bio)
213+{
214+ return 0;
215+}
216+#endif /* CONFIG_NEED_BOUNCE_POOL */
217+
181218 static void __blk_queue_bounce(struct request_queue *q, struct bio **bio_orig,
182− mempool_t *pool)
219+ mempool_t *pool, int force)
183220 {
184221 struct page *page;
185222 struct bio *bio = NULL;
@@ -192,7 +229,7 @@ static void __blk_queue_bounce(struct request_queue *q, struct bio **bio_orig, · 6 unmodified lines
192229 /*
193230 * is destination page below bounce pfn?
194231 */
195− if (page_to_pfn(page) <= queue_bounce_pfn(q))
232+ if (page_to_pfn(page) <= queue_bounce_pfn(q) && !force)
196233 continue;
197234
198235 /*
@@ -270,6 +307,7 @@ static void __blk_queue_bounce(struct request_queue *q, struct bio **bio_orig, · 71 unmodified lines
270307
271308 void blk_queue_bounce(struct request_queue *q, struct bio **bio_orig)
272309 {
310+ int must_bounce;
273311 mempool_t *pool;
274312
275313 /*
@@ -278,13 +316,15 @@ void blk_queue_bounce(struct request_queue *q, struct bio **bio_orig) · 2 unmodified lines
278316 if (!bio_has_data(*bio_orig))
279317 return;
280318
319+ must_bounce = must_snapshot_stable_pages(q, *bio_orig);
320+
281321 /*
282322 * for non-isa bounce case, just check if the bounce pfn is equal
283323 * to or bigger than the highest pfn in the system -- in that case,
284324 * don't waste time iterating over bio segments
285325 */
286326 if (!(q->bounce_gfp & GFP_DMA)) {
287− if (queue_bounce_pfn(q) >= blk_max_pfn)
327+ if (queue_bounce_pfn(q) >= blk_max_pfn && !must_bounce)
288328 return;
289329 pool = page_pool;
290330 } else {
@@ -295,7 +335,7 @@ void blk_queue_bounce(struct request_queue *q, struct bio **bio_orig) · 4 unmodified lines
295335 /*
296336 * slow path
297337 */
298− __blk_queue_bounce(q, bio_orig, pool);
338+ __blk_queue_bounce(q, bio_orig, pool, must_bounce);
299339 }
300340
301341 EXPORT_SYMBOL(blk_queue_bounce);
mm/page-writeback.c+4−0
@@ -2306,6 +2306,10 @@ void wait_for_stable_page(struct page *page) · 2305 unmodified lines
23062306
23072307 if (!bdi_cap_stable_pages_required(bdi))
23082308 return;
2309+#ifdef CONFIG_NEED_BOUNCE_POOL
2310+ if (mapping->host->i_sb->s_flags & MS_SNAP_STABLE)
2311+ return;
2312+#endif /* CONFIG_NEED_BOUNCE_POOL */
23092313
23102314 wait_on_page_writeback(page);
23112315 }