summaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle
AgeCommit message (Expand)Author
2011-02-15Merge branch 'master' into for-nextJiri Kosina
2011-01-19Kill off warning: ‘inline’ is not at beginning of declarationJesper Juhl
2011-01-12Merge branch 'cpuidle-perf-events' into idle-testLen Brown
2011-01-12Merge branch 'linus' into idle-testLen Brown
2011-01-12cpuidle/x86/perf: fix power:cpu_idle double end events and throw cpu_idle eve...Thomas Renninger
2011-01-12cpuidle: delete NOP CPUIDLE_FLAG_POLLLen Brown
2011-01-12cpuidle: Rename X86 specific idle poll state[0] from C0 to POLLThomas Renninger
2011-01-12cpuidle: Make cpuidle_enable_device() call poll_idle_init()Rafael J. Wysocki
2011-01-07Merge branch 'for-2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/tj...Linus Torvalds
2011-01-04perf: Clean up power events by introducing new, more generic onesThomas Renninger
2010-12-17drivers: Replace __get_cpu_var with __this_cpu_read if not used for an address.Christoph Lameter
2010-09-28cpuidle: Fix typosLucas De Marchi
2010-08-09cpuidle: extend cpuidle and menu governor to handle dynamic statesAi Li
2010-08-03[CPUFREQ] x86 cpufreq: Make trace_power_frequency cpufreq driver independentThomas Renninger
2010-07-01sched: Cure nr_iowait_cpu() usersPeter Zijlstra
2010-05-28Merge branch 'idle-release' of git://git.kernel.org/pub/scm/linux/kernel/git/...Linus Torvalds
2010-05-27cpuidle: make cpuidle_curr_driver staticLen Brown
2010-05-27cpuidle: add cpuidle_unregister_driver() error checkLen Brown
2010-05-25cpuidle: add a repeating pattern detector to the menu governorArjan van de Ven
2010-05-10PM QOS updateMark Gross
2010-05-09cpuidle: Fix incorrect optimizationArjan van de Ven
2010-03-30include cleanup: Update gfp.h and slab.h includes to prepare for breaking imp...Tejun Heo
2010-03-07Driver core: Constify struct sysfs_ops in struct kobj_typeEmese Revfy
2010-03-07sysdev: Pass attribute in sysdev_class attributes show/storeAndi Kleen
2010-03-06cpuidle menu: remove 8 bytes of padding on 64 bit buildsRichard Kennedy
2010-01-11drivers/cpuidle/governors/menu.c: fix undefined reference to `__udivdi3'Stephen Hemminger
2009-12-15drivers/cpuidle: Move dereference after NULL testJulia Lawall
2009-11-09tree-wide: fix typos "aquire" -> "acquire", "cumsumed" -> "consumed"Uwe Kleine-König
2009-10-29cpuidle: always return with interrupts enabledKevin Hilman
2009-09-22cpuidle: menu governor: reduce latency on exitCorrado Zoccolo
2009-09-22cpuidle: fix the menu governor to boost IO performanceArjan van de Ven
2009-09-19tracing, x86, cpuidle: Move the end point of a C state in the power tracerArjan van de Ven
2008-12-30cpuidle: Add decaying history logic to menu idle predictorPallipadi, Venkatesh
2008-11-09regression: disable timer peek-ahead for 2.6.28Arjan van de Ven
2008-10-23Merge branch 'v28-range-hrtimers-for-linus-v2' of git://git.kernel.org/pub/sc...Linus Torvalds
2008-10-16cpuidle: upon BIOS bug, default to default_idle rather than pollingVenkatesh Pallipadi
2008-10-16cpuidle: use last_state which can reflect the actual state enteredVenkatesh Pallipadi
2008-09-11hrtimer: peek at the timer queue just before going idleArjan van de Ven
2008-08-15cpuidle: Make ladder governor honor latency requirements fullyvenkatesh.pallipadi@intel.com
2008-08-15cpuidle: Menu governor fix wrong usage of measured_usvenkatesh.pallipadi@intel.com
2008-08-15cpuidle: Do not use poll_idle unless user asks for itvenkatesh.pallipadi@intel.com
2008-08-12cpuidle: make sysfs attributes sysdev class attributesRabin Vincent
2008-07-28ACPI/CPUIDLE: prevent setting pm_idle to NULLThomas Gleixner
2008-07-21sysdev: Pass the attribute to the low level sysdev show/store functionAndi Kleen
2008-06-26smp_call_function: get rid of the unused nonatomic/retry argumentJens Axboe
2008-06-11cpuidle acpi driver: fix oops on AC<->DCVenkatesh Pallipadi
2008-03-26cpuidle: fix 100% C0 statistics regressionVenki Pallipadi
2008-03-26cpuidle: fix cpuidle time and usage overflowYi Yang
2008-02-14ACPI, cpuidle: Clarify C-state description in sysfsVenkatesh Pallipadi
2008-02-09cpuidle: build fix for non-x86Venki Pallipadi
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717
/*
 * fs/mpage.c
 *
 * Copyright (C) 2002, Linus Torvalds.
 *
 * Contains functions related to preparing and submitting BIOs which contain
 * multiple pagecache pages.
 *
 * 15May2002	Andrew Morton
 *		Initial version
 * 27Jun2002	axboe@suse.de
 *		use bio_add_page() to build bio's just the right size
 */

#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/mm.h>
#include <linux/kdev_t.h>
#include <linux/gfp.h>
#include <linux/bio.h>
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <linux/blkdev.h>
#include <linux/highmem.h>
#include <linux/prefetch.h>
#include <linux/mpage.h>
#include <linux/writeback.h>
#include <linux/backing-dev.h>
#include <linux/pagevec.h>
#include <linux/cleancache.h>
#include "internal.h"

/*
 * I/O completion handler for multipage BIOs.
 *
 * The mpage code never puts partial pages into a BIO (except for end-of-file).
 * If a page does not map to a contiguous run of blocks then it simply falls
 * back to block_read_full_page().
 *
 * Why is this?  If a page's completion depends on a number of different BIOs
 * which can complete in any order (or at the same time) then determining the
 * status of that page is hard.  See end_buffer_async_read() for the details.
 * There is no point in duplicating all that complexity.
 */
static void mpage_end_io(struct bio *bio, int err)
{
	struct bio_vec *bv;
	int i;

	bio_for_each_segment_all(bv, bio, i) {
		struct page *page = bv->bv_page;
		page_endio(page, bio_data_dir(bio), err);
	}

	bio_put(bio);
}

static struct bio *mpage_bio_submit(int rw, struct bio *bio)
{
	bio->bi_end_io = mpage_end_io;
	guard_bio_eod(rw, bio);
	submit_bio(rw, bio);
	return NULL;
}

static struct bio *
mpage_alloc(struct block_device *bdev,
		sector_t first_sector, int nr_vecs,
		gfp_t gfp_flags)
{
	struct bio *bio;

	bio = bio_alloc(gfp_flags, nr_vecs);

	if (bio == NULL && (current->flags & PF_MEMALLOC)) {
		while (!bio && (nr_vecs /= 2))
			bio = bio_alloc(gfp_flags, nr_vecs);
	}

	if (bio) {
		bio->bi_bdev = bdev;
		bio->bi_iter.bi_sector = first_sector;
	}
	return bio;
}

/*
 * support function for mpage_readpages.  The fs supplied get_block might
 * return an up to date buffer.  This is used to map that buffer into
 * the page, which allows readpage to avoid triggering a duplicate call
 * to get_block.
 *
 * The idea is to avoid adding buffers to pages that don't already have
 * them.  So when the buffer is up to date and the page size == block size,
 * this marks the page up to date instead of adding new buffers.
 */
static void 
map_buffer_to_page(struct page *page, struct buffer_head *bh, int page_block) 
{
	struct inode *inode = page->mapping->host;
	struct buffer_head *page_bh, *head;
	int block = 0;

	if (!page_has_buffers(page)) {
		/*
		 * don't make any buffers if there is only one buffer on
		 * the page and the page just needs to be set up to date
		 */
		if (inode->i_blkbits == PAGE_CACHE_SHIFT && 
		    buffer_uptodate(bh)) {
			SetPageUptodate(page);    
			return;
		}
		create_empty_buffers(page, 1 << inode->i_blkbits, 0);
	}
	head = page_buffers(page);
	page_bh = head;
	do {
		if (block == page_block) {
			page_bh->b_state = bh->b_state;
			page_bh->b_bdev = bh->b_bdev;
			page_bh->b_blocknr = bh->b_blocknr;
			break;
		}
		page_bh = page_bh->b_this_page;
		block++;
	} while (page_bh != head);
}

/*
 * This is the worker routine which does all the work of mapping the disk
 * blocks and constructs largest possible bios, submits them for IO if the
 * blocks are not contiguous on the disk.
 *
 * We pass a buffer_head back and forth and use its buffer_mapped() flag to
 * represent the validity of its disk mapping and to decide when to do the next
 * get_block() call.
 */
static struct bio *
do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
		sector_t *last_block_in_bio, struct buffer_head *map_bh,
		unsigned long *first_logical_block, get_block_t get_block)
{
	struct inode *inode = page->mapping->host;
	const unsigned blkbits = inode->i_blkbits;
	const unsigned blocks_per_page = PAGE_CACHE_SIZE >> blkbits;
	const unsigned blocksize = 1 << blkbits;
	sector_t block_in_file;
	sector_t last_block;
	sector_t last_block_in_file;
	sector_t blocks[MAX_BUF_PER_PAGE];
	unsigned page_block;
	unsigned first_hole = blocks_per_page;
	struct block_device *bdev = NULL;
	int length;
	int fully_mapped = 1;
	unsigned nblocks;
	unsigned relative_block;

	if (page_has_buffers(page))
		goto confused;

	block_in_file = (sector_t)page->index << (PAGE_CACHE_SHIFT - blkbits);
	last_block = block_in_file + nr_pages * blocks_per_page;
	last_block_in_file = (i_size_read(inode) + blocksize - 1) >> blkbits;
	if (last_block > last_block_in_file)
		last_block = last_block_in_file;
	page_block = 0;

	/*
	 * Map blocks using the result from the previous get_blocks call first.
	 */
	nblocks = map_bh->b_size >> blkbits;
	if (buffer_mapped(map_bh) && block_in_file > *first_logical_block &&
			block_in_file < (*first_logical_block + nblocks)) {
		unsigned map_offset = block_in_file - *first_logical_block;
		unsigned last = nblocks - map_offset;

		for (relative_block = 0; ; relative_block++) {
			if (relative_block == last) {
				clear_buffer_mapped(map_bh);
				break;
			}
			if (page_block == blocks_per_page)
				break;
			blocks[page_block] = map_bh->b_blocknr + map_offset +
						relative_block;
			page_block++;
			block_in_file++;
		}
		bdev = map_bh->b_bdev;
	}

	/*
	 * Then do more get_blocks calls until we are done with this page.
	 */
	map_bh->b_page = page;
	while (page_block < blocks_per_page) {
		map_bh->b_state = 0;
		map_bh->b_size = 0;

		if (block_in_file < last_block) {
			map_bh->b_size = (last_block-block_in_file) << blkbits;
			if (get_block(inode, block_in_file, map_bh, 0))
				goto confused;
			*first_logical_block = block_in_file;
		}