⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filemap.c

📁 最新最稳定的Linux内存管理模块源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
EXPORT_SYMBOL(add_to_page_cache_locked);int add_to_page_cache_lru(struct page *page, struct address_space *mapping,				pgoff_t offset, gfp_t gfp_mask){	int ret;	/*	 * Splice_read and readahead add shmem/tmpfs pages into the page cache	 * before shmem_readpage has a chance to mark them as SwapBacked: they	 * need to go on the active_anon lru below, and mem_cgroup_cache_charge	 * (called in add_to_page_cache) needs to know where they're going too.	 */	if (mapping_cap_swap_backed(mapping))		SetPageSwapBacked(page);	ret = add_to_page_cache(page, mapping, offset, gfp_mask);	if (ret == 0) {		if (page_is_file_cache(page))			lru_cache_add_file(page);		else			lru_cache_add_active_anon(page);	}	return ret;}#ifdef CONFIG_NUMAstruct page *__page_cache_alloc(gfp_t gfp){	if (cpuset_do_page_mem_spread()) {		int n = cpuset_mem_spread_node();		return alloc_pages_node(n, gfp, 0);	}	return alloc_pages(gfp, 0);}EXPORT_SYMBOL(__page_cache_alloc);#endifstatic int __sleep_on_page_lock(void *word){	io_schedule();	return 0;}/* * In order to wait for pages to become available there must be * waitqueues associated with pages. By using a hash table of * waitqueues where the bucket discipline is to maintain all * waiters on the same queue and wake all when any of the pages * become available, and for the woken contexts to check to be * sure the appropriate page became available, this saves space * at a cost of "thundering herd" phenomena during rare hash * collisions. */static wait_queue_head_t *page_waitqueue(struct page *page){	const struct zone *zone = page_zone(page);	return &zone->wait_table[hash_ptr(page, zone->wait_table_bits)];}static inline void wake_up_page(struct page *page, int bit){	__wake_up_bit(page_waitqueue(page), &page->flags, bit);}void wait_on_page_bit(struct page *page, int bit_nr){	DEFINE_WAIT_BIT(wait, &page->flags, bit_nr);	if (test_bit(bit_nr, &page->flags))		__wait_on_bit(page_waitqueue(page), &wait, sync_page,							TASK_UNINTERRUPTIBLE);}EXPORT_SYMBOL(wait_on_page_bit);/** * unlock_page - unlock a locked page * @page: the page * * Unlocks the page and wakes up sleepers in ___wait_on_page_locked(). * Also wakes sleepers in wait_on_page_writeback() because the wakeup * mechananism between PageLocked pages and PageWriteback pages is shared. * But that's OK - sleepers in wait_on_page_writeback() just go back to sleep. * * The mb is necessary to enforce ordering between the clear_bit and the read * of the waitqueue (to avoid SMP races with a parallel wait_on_page_locked()). */void unlock_page(struct page *page){	VM_BUG_ON(!PageLocked(page));	clear_bit_unlock(PG_locked, &page->flags);	smp_mb__after_clear_bit();	wake_up_page(page, PG_locked);}EXPORT_SYMBOL(unlock_page);/** * end_page_writeback - end writeback against a page * @page: the page */void end_page_writeback(struct page *page){	if (TestClearPageReclaim(page))		rotate_reclaimable_page(page);	if (!test_clear_page_writeback(page))		BUG();	smp_mb__after_clear_bit();	wake_up_page(page, PG_writeback);}EXPORT_SYMBOL(end_page_writeback);/** * __lock_page - get a lock on the page, assuming we need to sleep to get it * @page: the page to lock * * Ugly. Running sync_page() in state TASK_UNINTERRUPTIBLE is scary.  If some * random driver's requestfn sets TASK_RUNNING, we could busywait.  However * chances are that on the second loop, the block layer's plug list is empty, * so sync_page() will then return in state TASK_UNINTERRUPTIBLE. */void __lock_page(struct page *page){	DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);	__wait_on_bit_lock(page_waitqueue(page), &wait, sync_page,							TASK_UNINTERRUPTIBLE);}EXPORT_SYMBOL(__lock_page);int __lock_page_killable(struct page *page){	DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);	return __wait_on_bit_lock(page_waitqueue(page), &wait,					sync_page_killable, TASK_KILLABLE);}/** * __lock_page_nosync - get a lock on the page, without calling sync_page() * @page: the page to lock * * Variant of lock_page that does not require the caller to hold a reference * on the page's mapping. */void __lock_page_nosync(struct page *page){	DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);	__wait_on_bit_lock(page_waitqueue(page), &wait, __sleep_on_page_lock,							TASK_UNINTERRUPTIBLE);}/** * find_get_page - find and get a page reference * @mapping: the address_space to search * @offset: the page index * * Is there a pagecache struct page at the given (mapping, offset) tuple? * If yes, increment its refcount and return it; if no, return NULL. */struct page *find_get_page(struct address_space *mapping, pgoff_t offset){	void **pagep;	struct page *page;	rcu_read_lock();repeat:	page = NULL;	pagep = radix_tree_lookup_slot(&mapping->page_tree, offset);	if (pagep) {		page = radix_tree_deref_slot(pagep);		if (unlikely(!page || page == RADIX_TREE_RETRY))			goto repeat;		if (!page_cache_get_speculative(page))			goto repeat;		/*		 * Has the page moved?		 * This is part of the lockless pagecache protocol. See		 * include/linux/pagemap.h for details.		 */		if (unlikely(page != *pagep)) {			page_cache_release(page);			goto repeat;		}	}	rcu_read_unlock();	return page;}EXPORT_SYMBOL(find_get_page);/** * find_lock_page - locate, pin and lock a pagecache page * @mapping: the address_space to search * @offset: the page index * * Locates the desired pagecache page, locks it, increments its reference * count and returns its address. * * Returns zero if the page was not present. find_lock_page() may sleep. */struct page *find_lock_page(struct address_space *mapping, pgoff_t offset){	struct page *page;repeat:	page = find_get_page(mapping, offset);	if (page) {		lock_page(page);		/* Has the page been truncated? */		if (unlikely(page->mapping != mapping)) {			unlock_page(page);			page_cache_release(page);			goto repeat;		}		VM_BUG_ON(page->index != offset);	}	return page;}EXPORT_SYMBOL(find_lock_page);/** * find_or_create_page - locate or add a pagecache page * @mapping: the page's address_space * @index: the page's index into the mapping * @gfp_mask: page allocation mode * * Locates a page in the pagecache.  If the page is not present, a new page * is allocated using @gfp_mask and is added to the pagecache and to the VM's * LRU list.  The returned page is locked and has its reference count * incremented. * * find_or_create_page() may sleep, even if @gfp_flags specifies an atomic * allocation! * * find_or_create_page() returns the desired page's address, or zero on * memory exhaustion. */struct page *find_or_create_page(struct address_space *mapping,		pgoff_t index, gfp_t gfp_mask){	struct page *page;	int err;repeat:	page = find_lock_page(mapping, index);	if (!page) {		page = __page_cache_alloc(gfp_mask);		if (!page)			return NULL;		/*		 * We want a regular kernel memory (not highmem or DMA etc)		 * allocation for the radix tree nodes, but we need to honour		 * the context-specific requirements the caller has asked for.		 * GFP_RECLAIM_MASK collects those requirements.		 */		err = add_to_page_cache_lru(page, mapping, index,			(gfp_mask & GFP_RECLAIM_MASK));		if (unlikely(err)) {			page_cache_release(page);			page = NULL;			if (err == -EEXIST)				goto repeat;		}	}	return page;}EXPORT_SYMBOL(find_or_create_page);/** * find_get_pages - gang pagecache lookup * @mapping:	The address_space to search * @start:	The starting page index * @nr_pages:	The maximum number of pages * @pages:	Where the resulting pages are placed * * find_get_pages() will search for and return a group of up to * @nr_pages pages in the mapping.  The pages are placed at @pages. * find_get_pages() takes a reference against the returned pages. * * The search returns a group of mapping-contiguous pages with ascending * indexes.  There may be holes in the indices due to not-present pages. * * find_get_pages() returns the number of pages which were found. */unsigned find_get_pages(struct address_space *mapping, pgoff_t start,			    unsigned int nr_pages, struct page **pages){	unsigned int i;	unsigned int ret;	unsigned int nr_found;	rcu_read_lock();restart:	nr_found = radix_tree_gang_lookup_slot(&mapping->page_tree,				(void ***)pages, start, nr_pages);	ret = 0;	for (i = 0; i < nr_found; i++) {		struct page *page;repeat:		page = radix_tree_deref_slot((void **)pages[i]);		if (unlikely(!page))			continue;		/*		 * this can only trigger if nr_found == 1, making livelock		 * a non issue.		 */		if (unlikely(page == RADIX_TREE_RETRY))			goto restart;		if (!page_cache_get_speculative(page))			goto repeat;		/* Has the page moved? */		if (unlikely(page != *((void **)pages[i]))) {			page_cache_release(page);			goto repeat;		}		pages[ret] = page;		ret++;	}	rcu_read_unlock();	return ret;}/** * find_get_pages_contig - gang contiguous pagecache lookup * @mapping:	The address_space to search * @index:	The starting page index * @nr_pages:	The maximum number of pages * @pages:	Where the resulting pages are placed * * find_get_pages_contig() works exactly like find_get_pages(), except * that the returned number of pages are guaranteed to be contiguous. * * find_get_pages_contig() returns the number of pages which were found. */unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index,			       unsigned int nr_pages, struct page **pages){	unsigned int i;	unsigned int ret;	unsigned int nr_found;	rcu_read_lock();restart:	nr_found = radix_tree_gang_lookup_slot(&mapping->page_tree,				(void ***)pages, index, nr_pages);	ret = 0;	for (i = 0; i < nr_found; i++) {		struct page *page;repeat:		page = radix_tree_deref_slot((void **)pages[i]);		if (unlikely(!page))			continue;		/*		 * this can only trigger if nr_found == 1, making livelock		 * a non issue.		 */		if (unlikely(page == RADIX_TREE_RETRY))			goto restart;		if (page->mapping == NULL || page->index != index)			break;		if (!page_cache_get_speculative(page))			goto repeat;		/* Has the page moved? */		if (unlikely(page != *((void **)pages[i]))) {			page_cache_release(page);			goto repeat;		}		pages[ret] = page;		ret++;		index++;	}	rcu_read_unlock();	return ret;}EXPORT_SYMBOL(find_get_pages_contig);/** * find_get_pages_tag - find and return pages that match @tag * @mapping:	the address_space to search * @index:	the starting page index * @tag:	the tag index * @nr_pages:	the maximum number of pages * @pages:	where the resulting pages are placed * * Like find_get_pages, except we only return pages which are tagged with * @tag.   We update @index to index the next page for the traversal. */unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,			int tag, unsigned int nr_pages, struct page **pages){	unsigned int i;	unsigned int ret;	unsigned int nr_found;	rcu_read_lock();restart:	nr_found = radix_tree_gang_lookup_tag_slot(&mapping->page_tree,				(void ***)pages, *index, nr_pages, tag);	ret = 0;	for (i = 0; i < nr_found; i++) {		struct page *page;repeat:		page = radix_tree_deref_slot((void **)pages[i]);		if (unlikely(!page))			continue;		/*		 * this can only trigger if nr_found == 1, making livelock		 * a non issue.		 */		if (unlikely(page == RADIX_TREE_RETRY))			goto restart;		if (!page_cache_get_speculative(page))			goto repeat;		/* Has the page moved? */		if (unlikely(page != *((void **)pages[i]))) {			page_cache_release(page);			goto repeat;		}		pages[ret] = page;		ret++;	}	rcu_read_unlock();	if (ret)		*index = pages[ret - 1]->index + 1;	return ret;}EXPORT_SYMBOL(find_get_pages_tag);/** * grab_cache_page_nowait - returns locked page at given index in given cache * @mapping: target address_space * @index: the page index * * Same as grab_cache_page(), but do not wait if the page is unavailable. * This is intended for speculative data generators, where the data can * be regenerated if the page couldn't be grabbed.  This routine should * be safe to call while holding the lock for another page. * * Clear __GFP_FS when allocating the page to avoid recursion into the fs * and deadlock against the caller's locked page. */struct page *grab_cache_page_nowait(struct address_space *mapping, pgoff_t index){	struct page *page = find_get_page(mapping, index);	if (page) {		if (trylock_page(page))			return page;		page_cache_release(page);		return NULL;	}	page = __page_cache_alloc(mapping_gfp_mask(mapping) & ~__GFP_FS);	if (page && add_to_page_cache_lru(page, mapping, index, GFP_NOFS)) {		page_cache_release(page);		page = NULL;	}	return page;}EXPORT_SYMBOL(grab_cache_page_nowait);/* * CD/DVDs are error prone. When a medium error occurs, the driver may fail * a _large_ part of the i/o request. Imagine the worst scenario: * *      ---R__________________________________________B__________ *         ^ reading here                             ^ bad block(assume 4k) * * read(R) => miss => readahead(R...B) => media error => frustrating retries * => failing the whole request => read(R) => read(R+1) => * readahead(R+1...B+1) => bang => read(R+2) => read(R+3) => * readahead(R+3...B+2) => bang => read(R+3) => read(R+4) => * readahead(R+4...B+3) => bang => read(R+4) => read(R+5) => ...... *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -