diff options
| author | Linus Torvalds <torvalds@penguin.transmeta.com> | 2002-04-09 23:31:49 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@penguin.transmeta.com> | 2002-04-09 23:31:49 -0700 |
| commit | 48fe688958ed01aa3adbc63ef9f90bd1a849cdb7 (patch) | |
| tree | 0273e7983d10338c3635088cc87cc18bd8cb5614 /include/linux | |
| parent | 0c4a2e9ca79417da7d8f22f7861d8e249e0cfe41 (diff) | |
| parent | 5e5a291ecb2efae6149bec1a4b601c9c495117aa (diff) | |
Merge bk://ppc.bkbits.net/for-linus-ppc
into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/blkdev.h | 12 | ||||
| -rw-r--r-- | include/linux/fs.h | 38 | ||||
| -rw-r--r-- | include/linux/hfs_sysdep.h | 6 | ||||
| -rw-r--r-- | include/linux/mm.h | 41 | ||||
| -rw-r--r-- | include/linux/pagemap.h | 71 | ||||
| -rw-r--r-- | include/linux/radix-tree.h | 49 | ||||
| -rw-r--r-- | include/linux/raid/md_k.h | 1 | ||||
| -rw-r--r-- | include/linux/sched.h | 1 | ||||
| -rw-r--r-- | include/linux/swap.h | 5 |
9 files changed, 154 insertions, 70 deletions
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 7a43ff774fe0..914498e8e4b9 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -153,6 +153,12 @@ struct request_queue prep_rq_fn *prep_rq_fn; /* + * The VM-level readahead tunable for this device. In + * units of 512-byte sectors. + */ + unsigned ra_sectors; + + /* * The queue owner gets to use this for whatever they like. * ll_rw_blk doesn't touch it. */ @@ -308,6 +314,8 @@ extern void blk_queue_hardsect_size(request_queue_t *q, unsigned short); extern void blk_queue_segment_boundary(request_queue_t *q, unsigned long); extern void blk_queue_assign_lock(request_queue_t *q, spinlock_t *); extern void blk_queue_prep_rq(request_queue_t *q, prep_rq_fn *pfn); +extern int blk_set_readahead(kdev_t dev, unsigned sectors); +extern unsigned blk_get_readahead(kdev_t dev); extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *); extern void blk_dump_rq_flags(struct request *, char *); @@ -322,10 +330,6 @@ extern int * blksize_size[MAX_BLKDEV]; #define MAX_SEGMENT_SIZE 65536 -/* read-ahead in pages.. */ -#define MAX_READAHEAD 31 -#define MIN_READAHEAD 3 - #define blkdev_entry_to_request(entry) list_entry((entry), struct request, queuelist) extern void drive_stat_acct(struct request *, int, int); diff --git a/include/linux/fs.h b/include/linux/fs.h index 20928d804327..ce6bd67e4cc9 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -21,6 +21,7 @@ #include <linux/cache.h> #include <linux/stddef.h> #include <linux/string.h> +#include <linux/radix-tree.h> #include <asm/atomic.h> #include <asm/bitops.h> @@ -172,12 +173,10 @@ extern int leases_enable, dir_notify_enable, lease_break_time; #define BLKRRPART _IO(0x12,95) /* re-read partition table */ #define BLKGETSIZE _IO(0x12,96) /* return device size /512 (long *arg) */ #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */ -#if 0 /* Obsolete, these don't do anything. */ #define BLKRASET _IO(0x12,98) /* set read ahead for block device */ #define BLKRAGET _IO(0x12,99) /* get current read ahead setting */ #define BLKFRASET _IO(0x12,100)/* set filesystem (mm/filemap.c) read-ahead */ #define BLKFRAGET _IO(0x12,101)/* get filesystem (mm/filemap.c) read-ahead */ -#endif #define BLKSECTSET _IO(0x12,102)/* set max sectors per request (ll_rw_blk.c) */ #define BLKSECTGET _IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */ #define BLKSSZGET _IO(0x12,104)/* get block device sector size */ @@ -286,6 +285,24 @@ extern void set_bh_page(struct buffer_head *bh, struct page *page, unsigned long #define touch_buffer(bh) mark_page_accessed(bh->b_page) +/* If we *know* page->private refers to buffer_heads */ +#define page_buffers(page) \ + ({ \ + if (!PagePrivate(page)) \ + BUG(); \ + ((struct buffer_head *)(page)->private); \ + }) +#define page_has_buffers(page) PagePrivate(page) +#define set_page_buffers(page, buffers) \ + do { \ + SetPagePrivate(page); \ + page->private = (unsigned long)buffers; \ + } while (0) +#define clear_page_buffers(page) \ + do { \ + ClearPagePrivate(page); \ + page->private = 0; \ + } while (0) #include <linux/pipe_fs_i.h> /* #include <linux/umsdos_fs_i.h> */ @@ -370,6 +387,8 @@ struct address_space_operations { }; struct address_space { + struct radix_tree_root page_tree; /* radix tree of all pages */ + rwlock_t page_lock; /* and rwlock protecting it */ struct list_head clean_pages; /* list of clean pages */ struct list_head dirty_pages; /* list of dirty pages */ struct list_head locked_pages; /* list of locked pages */ @@ -484,6 +503,18 @@ struct fown_struct { int signum; /* posix.1b rt signal to be delivered on IO */ }; +/* + * Track a single file's readahead state + */ +struct file_ra_state { + unsigned long start; /* Current window */ + unsigned long size; + unsigned long next_size; /* Next window size */ + unsigned long prev_page; /* Cache last read() position */ + unsigned long ahead_start; /* Ahead window */ + unsigned long ahead_size; +}; + struct file { struct list_head f_list; struct dentry *f_dentry; @@ -493,10 +524,10 @@ struct file { unsigned int f_flags; mode_t f_mode; loff_t f_pos; - unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin; struct fown_struct f_owner; unsigned int f_uid, f_gid; int f_error; + struct file_ra_state f_ra; unsigned long f_version; @@ -925,6 +956,7 @@ struct super_block *get_sb_single(struct file_system_type *fs_type, struct super_block *get_sb_nodev(struct file_system_type *fs_type, int flags, void *data, int (*fill_super)(struct super_block *, void *, int)); +void generic_shutdown_super(struct super_block *sb); void kill_block_super(struct super_block *sb); void kill_anon_super(struct super_block *sb); void kill_litter_super(struct super_block *sb); diff --git a/include/linux/hfs_sysdep.h b/include/linux/hfs_sysdep.h index ab6c834d0f31..62fcf2ea311f 100644 --- a/include/linux/hfs_sysdep.h +++ b/include/linux/hfs_sysdep.h @@ -200,16 +200,16 @@ static inline void *hfs_buffer_data(const hfs_buffer buffer) { #endif static inline int hfs_clear_bit(int bitnr, hfs_u32 *lword) { - return test_and_clear_bit(BITNR(bitnr), lword); + return test_and_clear_bit(BITNR(bitnr), (unsigned long *)lword); } static inline int hfs_set_bit(int bitnr, hfs_u32 *lword) { - return test_and_set_bit(BITNR(bitnr), lword); + return test_and_set_bit(BITNR(bitnr), (unsigned long *)lword); } static inline int hfs_test_bit(int bitnr, const hfs_u32 *lword) { /* the kernel should declare the second arg of test_bit as const */ - return test_bit(BITNR(bitnr), (void *)lword); + return test_bit(BITNR(bitnr), (unsigned long *)lword); } #undef BITNR diff --git a/include/linux/mm.h b/include/linux/mm.h index 35ea7c71b53e..948e0ca2b480 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -149,15 +149,12 @@ typedef struct page { struct list_head list; /* ->mapping has some page lists. */ struct address_space *mapping; /* The inode (or ...) we belong to. */ unsigned long index; /* Our offset within mapping. */ - struct page *next_hash; /* Next page sharing our hash bucket in - the pagecache hash table. */ atomic_t count; /* Usage count, see below. */ unsigned long flags; /* atomic flags, some possibly updated asynchronously */ struct list_head lru; /* Pageout list, eg. active_list; protected by pagemap_lru_lock !! */ - struct page **pprev_hash; /* Complement to *next_hash. */ - struct buffer_head * buffers; /* Buffer maps us to a disk block. */ + unsigned long private; /* fs-private opaque data */ /* * On machines where all RAM is mapped into kernel address space, @@ -180,7 +177,7 @@ typedef struct page { * * What counts for a page usage: * - cache mapping (page->mapping) - * - disk mapping (page->buffers) + * - private data (page->private) * - page mapped in a task's page tables, each mapping * is counted separately * @@ -223,22 +220,23 @@ typedef struct page { * page->mapping is the pointer to the inode, and page->index is the * file offset of the page, in units of PAGE_CACHE_SIZE. * - * A page may have buffers allocated to it. In this case, - * page->buffers is a circular list of these buffer heads. Else, - * page->buffers == NULL. + * A page contains an opaque `private' member, which belongs to the + * page's address_space. Usually, this is the address of a circular + * list of the page's disk buffers. * + * The PG_private bitflag is set if page->private contains a valid + * value. * For pages belonging to inodes, the page->count is the number of - * attaches, plus 1 if buffers are allocated to the page, plus one - * for the page cache itself. + * attaches, plus 1 if `private' contains something, plus one for + * the page cache itself. * * All pages belonging to an inode are in these doubly linked lists: * mapping->clean_pages, mapping->dirty_pages and mapping->locked_pages; * using the page->list list_head. These fields are also used for * freelist managemet (when page->count==0). * - * There is also a hash table mapping (mapping,index) to the page - * in memory if present. The lists for this hash table use the fields - * page->next_hash and page->pprev_hash. + * There is also a per-mapping radix tree mapping index to the page + * in memory if present. The tree is rooted at mapping->root. * * All process pages can do I/O: * - inode pages may need to be read from disk, @@ -294,6 +292,8 @@ typedef struct page { #define PG_reserved 14 #define PG_launder 15 /* written out by VM pressure.. */ +#define PG_private 16 /* Has something at ->private */ + /* Make it prettier to test the above... */ #define UnlockPage(page) unlock_page(page) #define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags) @@ -310,6 +310,9 @@ typedef struct page { #define PageLaunder(page) test_bit(PG_launder, &(page)->flags) #define SetPageLaunder(page) set_bit(PG_launder, &(page)->flags) #define __SetPageReserved(page) __set_bit(PG_reserved, &(page)->flags) +#define SetPagePrivate(page) set_bit(PG_private, &(page)->flags) +#define ClearPagePrivate(page) clear_bit(PG_private, &(page)->flags) +#define PagePrivate(page) test_bit(PG_private, &(page)->flags) /* * The zone field is never updated after free_area_init_core() @@ -470,7 +473,7 @@ extern struct address_space swapper_space; static inline int is_page_cache_freeable(struct page * page) { - return page_count(page) - !!page->buffers == 1; + return page_count(page) - !!PagePrivate(page) == 1; } extern int can_share_swap_page(struct page *); @@ -535,6 +538,13 @@ extern void truncate_inode_pages(struct address_space *, loff_t); extern int filemap_sync(struct vm_area_struct *, unsigned long, size_t, unsigned int); extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int); +/* readahead.c */ +void do_page_cache_readahead(struct file *file, + unsigned long offset, unsigned long nr_to_read); +void page_cache_readahead(struct file *file, unsigned long offset); +void page_cache_readaround(struct file *file, unsigned long offset); +void handle_ra_thrashing(struct file *file); + /* vma is the first one with address < vma->vm_end, * and even address < vma->vm_start. Have to extend vma. */ static inline int expand_stack(struct vm_area_struct * vma, unsigned long address) @@ -579,6 +589,9 @@ static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * m extern struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr); +extern int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0); +extern int pdflush_flush(unsigned long nr_pages); + extern struct page * vmalloc_to_page(void *addr); #endif /* __KERNEL__ */ diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 242a576ea934..df7f5bd64367 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -41,53 +41,39 @@ static inline struct page *page_cache_alloc(struct address_space *x) */ #define page_cache_entry(x) virt_to_page(x) -extern unsigned int page_hash_bits; -#define PAGE_HASH_BITS (page_hash_bits) -#define PAGE_HASH_SIZE (1 << PAGE_HASH_BITS) - -extern atomic_t page_cache_size; /* # of pages currently in the hash table */ -extern struct page **page_hash_table; - -extern void page_cache_init(unsigned long); +extern atomic_t page_cache_size; /* # of pages currently in the page cache */ + +extern struct page * find_get_page(struct address_space *mapping, + unsigned long index); +extern struct page * find_lock_page(struct address_space *mapping, + unsigned long index); +extern struct page * find_trylock_page(struct address_space *mapping, + unsigned long index); +extern struct page * find_or_create_page(struct address_space *mapping, + unsigned long index, unsigned int gfp_mask); -/* - * We use a power-of-two hash table to avoid a modulus, - * and get a reasonable hash by knowing roughly how the - * inode pointer and indexes are distributed (ie, we - * roughly know which bits are "significant") - * - * For the time being it will work for struct address_space too (most of - * them sitting inside the inodes). We might want to change it later. - */ -static inline unsigned long _page_hashfn(struct address_space * mapping, unsigned long index) +extern struct page * grab_cache_page(struct address_space *mapping, + unsigned long index); +extern struct page * grab_cache_page_nowait(struct address_space *mapping, + unsigned long index); + +extern int add_to_page_cache(struct page *page, + struct address_space *mapping, unsigned long index); +extern int add_to_page_cache_unique(struct page *page, + struct address_space *mapping, unsigned long index); +static inline void ___add_to_page_cache(struct page *page, + struct address_space *mapping, unsigned long index) { -#define i (((unsigned long) mapping)/(sizeof(struct inode) & ~ (sizeof(struct inode) - 1))) -#define s(x) ((x)+((x)>>PAGE_HASH_BITS)) - return s(i+index) & (PAGE_HASH_SIZE-1); -#undef i -#undef s -} - -#define page_hash(mapping,index) (page_hash_table+_page_hashfn(mapping,index)) + list_add(&page->list, &mapping->clean_pages); + page->mapping = mapping; + page->index = index; -extern struct page * __find_get_page(struct address_space *mapping, - unsigned long index, struct page **hash); -#define find_get_page(mapping, index) \ - __find_get_page(mapping, index, page_hash(mapping, index)) -extern struct page * __find_lock_page (struct address_space * mapping, - unsigned long index, struct page **hash); -extern struct page * find_or_create_page(struct address_space *mapping, - unsigned long index, unsigned int gfp_mask); + mapping->nrpages++; + atomic_inc(&page_cache_size); +} extern void FASTCALL(lock_page(struct page *page)); extern void FASTCALL(unlock_page(struct page *page)); -#define find_lock_page(mapping, index) \ - __find_lock_page(mapping, index, page_hash(mapping, index)) -extern struct page *find_trylock_page(struct address_space *, unsigned long); - -extern void add_to_page_cache(struct page * page, struct address_space *mapping, unsigned long index); -extern void add_to_page_cache_locked(struct page * page, struct address_space *mapping, unsigned long index); -extern int add_to_page_cache_unique(struct page * page, struct address_space *mapping, unsigned long index, struct page **hash); extern void ___wait_on_page(struct page *); @@ -99,9 +85,6 @@ static inline void wait_on_page(struct page * page) extern void wake_up_page(struct page *); -extern struct page * grab_cache_page (struct address_space *, unsigned long); -extern struct page * grab_cache_page_nowait (struct address_space *, unsigned long); - typedef int filler_t(void *, struct page*); extern struct page *read_cache_page(struct address_space *, unsigned long, diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h new file mode 100644 index 000000000000..fb2e3f3350d3 --- /dev/null +++ b/include/linux/radix-tree.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2001 Momchil Velikov + * Portions Copyright (C) 2001 Christoph Hellwig + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef _LINUX_RADIX_TREE_H +#define _LINUX_RADIX_TREE_H + +struct radix_tree_node; + +#define RADIX_TREE_SLOT_RESERVED ((void *)~0UL) + +struct radix_tree_root { + unsigned int height; + int gfp_mask; + struct radix_tree_node *rnode; +}; + +#define RADIX_TREE_INIT(mask) {0, (mask), NULL} + +#define RADIX_TREE(name, mask) \ + struct radix_tree_root name = RADIX_TREE_INIT(mask) + +#define INIT_RADIX_TREE(root, mask) \ +do { \ + (root)->height = 0; \ + (root)->gfp_mask = (mask); \ + (root)->rnode = NULL; \ +} while (0) + +extern int radix_tree_reserve(struct radix_tree_root *, unsigned long, void ***); +extern int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); +extern void *radix_tree_lookup(struct radix_tree_root *, unsigned long); +extern int radix_tree_delete(struct radix_tree_root *, unsigned long); + +#endif /* _LINUX_RADIX_TREE_H */ diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index c0c21e26f2c3..997d45fa7be7 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -91,7 +91,6 @@ static inline mddev_t * kdev_to_mddev (kdev_t dev) /* * default readahead */ -#define MD_READAHEAD MAX_READAHEAD static inline int disk_faulty(mdp_disk_t * d) { diff --git a/include/linux/sched.h b/include/linux/sched.h index 024e34706cc9..f5fd7b435bd1 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -368,6 +368,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0) #define PF_MEMDIE 0x00001000 /* Killed for out-of-memory */ #define PF_FREE_PAGES 0x00002000 /* per process page freeing */ #define PF_NOIO 0x00004000 /* avoid generating further I/O */ +#define PF_FLUSHER 0x00008000 /* responsible for disk writeback */ /* * Ptrace flags diff --git a/include/linux/swap.h b/include/linux/swap.h index 824a928d5c37..a7a64ba55816 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -109,7 +109,7 @@ extern void __remove_inode_page(struct page *); struct task_struct; struct vm_area_struct; struct sysinfo; - +struct address_space; struct zone_t; /* linux/mm/swap.c */ @@ -139,6 +139,9 @@ extern void show_swap_cache_info(void); extern int add_to_swap_cache(struct page *, swp_entry_t); extern void __delete_from_swap_cache(struct page *page); extern void delete_from_swap_cache(struct page *page); +extern int move_to_swap_cache(struct page *page, swp_entry_t entry); +extern int move_from_swap_cache(struct page *page, unsigned long index, + struct address_space *mapping); extern void free_page_and_swap_cache(struct page *page); extern struct page * lookup_swap_cache(swp_entry_t); extern struct page * read_swap_cache_async(swp_entry_t); |
