📄 filemap.c
字号:
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 + -