+ struct metapage *mp;
+ unsigned int offset;
+
+ for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
+ mp = page_to_mp(page, offset);
+ if (mp && test_bit(META_io, &mp->flag)) {
+ if (mp->lsn)
+ remove_from_logsync(mp);
+ clear_bit(META_io, &mp->flag);
+ }
+ /*
+ * I'd like to call drop_metapage here, but I don't think it's
+ * safe unless I have the page locked
+ */
+ }
+ end_page_writeback(page);
+}
+
+static int metapage_write_end_io(struct bio *bio, unsigned int bytes_done,
+ int err)
+{
+ struct page *page = bio->bi_private;
+
+ BUG_ON(!PagePrivate(page));
+
+ if (bio->bi_size)
+ return 1;
+
+ if (! test_bit(BIO_UPTODATE, &bio->bi_flags)) {
+ printk(KERN_ERR "metapage_write_end_io: I/O error\n");
+ SetPageError(page);
+ }
+ dec_io(page, last_write_complete);
+ bio_put(bio);
+ return 0;
+}
+
+static int metapage_writepage(struct page *page, struct writeback_control *wbc)
+{
+ struct bio *bio = NULL;
+ unsigned int block_offset; /* block offset of mp within page */
+ struct inode *inode = page->mapping->host;
+ unsigned int blocks_per_mp = JFS_SBI(inode->i_sb)->nbperpage;
+ unsigned int len;
+ unsigned int xlen;
+ struct metapage *mp;
+ int redirty = 0;
+ sector_t lblock;
+ sector_t pblock;
+ sector_t next_block = 0;
+ sector_t page_start;
+ unsigned long bio_bytes = 0;
+ unsigned long bio_offset = 0;
+ unsigned int offset;
+
+ page_start = (sector_t)page->index <<
+ (PAGE_CACHE_SHIFT - inode->i_blkbits);
+ BUG_ON(!PageLocked(page));
+ BUG_ON(PageWriteback(page));
+
+ for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
+ mp = page_to_mp(page, offset);
+
+ if (!mp || !test_bit(META_dirty, &mp->flag))
+ continue;
+
+ if (mp->nohomeok && !test_bit(META_forcewrite, &mp->flag)) {
+ redirty = 1;
+ /*
+ * Make sure this page isn't blocked indefinitely.
+ * If the journal isn't undergoing I/O, push it
+ */
+ if (mp->log && !(mp->log->cflag & logGC_PAGEOUT))
+ jfs_flush_journal(mp->log, 0);
+ continue;
+ }
+
+ clear_bit(META_dirty, &mp->flag);
+ block_offset = offset >> inode->i_blkbits;
+ lblock = page_start + block_offset;
+ if (bio) {
+ if (xlen && lblock == next_block) {
+ /* Contiguous, in memory & on disk */
+ len = min(xlen, blocks_per_mp);
+ xlen -= len;
+ bio_bytes += len << inode->i_blkbits;
+ set_bit(META_io, &mp->flag);
+ continue;
+ }
+ /* Not contiguous */
+ if (bio_add_page(bio, page, bio_bytes, bio_offset) <
+ bio_bytes)
+ goto add_failed;
+ /*
+ * Increment counter before submitting i/o to keep
+ * count from hitting zero before we're through
+ */
+ inc_io(page);
+ if (!bio->bi_size)
+ goto dump_bio;
+ submit_bio(WRITE, bio);
+ bio = NULL;
+ } else {
+ set_page_writeback(page);
+ inc_io(page);
+ }
+ xlen = (PAGE_CACHE_SIZE - offset) >> inode->i_blkbits;
+ pblock = metapage_get_blocks(inode, lblock, &xlen);
+ if (!pblock) {
+ /* Need better error handling */
+ printk(KERN_ERR "JFS: metapage_get_blocks failed\n");
+ dec_io(page, last_write_complete);
+ continue;
+ }
+ set_bit(META_io, &mp->flag);
+ len = min(xlen, (uint) JFS_SBI(inode->i_sb)->nbperpage);
+
+ bio = bio_alloc(GFP_NOFS, 1);
+ bio->bi_bdev = inode->i_sb->s_bdev;
+ bio->bi_sector = pblock << (inode->i_blkbits - 9);
+ bio->bi_end_io = metapage_write_end_io;
+ bio->bi_private = page;
+
+ /* Don't call bio_add_page yet, we may add to this vec */
+ bio_offset = offset;
+ bio_bytes = len << inode->i_blkbits;
+
+ xlen -= len;
+ next_block = lblock + len;