summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@penguin.transmeta.com>2002-04-09 23:31:49 -0700
committerLinus Torvalds <torvalds@penguin.transmeta.com>2002-04-09 23:31:49 -0700
commit48fe688958ed01aa3adbc63ef9f90bd1a849cdb7 (patch)
tree0273e7983d10338c3635088cc87cc18bd8cb5614 /include/linux
parent0c4a2e9ca79417da7d8f22f7861d8e249e0cfe41 (diff)
parent5e5a291ecb2efae6149bec1a4b601c9c495117aa (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.h12
-rw-r--r--include/linux/fs.h38
-rw-r--r--include/linux/hfs_sysdep.h6
-rw-r--r--include/linux/mm.h41
-rw-r--r--include/linux/pagemap.h71
-rw-r--r--include/linux/radix-tree.h49
-rw-r--r--include/linux/raid/md_k.h1
-rw-r--r--include/linux/sched.h1
-rw-r--r--include/linux/swap.h5
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);