From 6e54ab36e19d4c76a51acb9d86388e4957182618 Mon Sep 17 00:00:00 2001 From: Simon Burley Date: Mon, 20 May 2002 01:40:50 -0700 Subject: Tigon3: Add Netgear GA320T support. --- include/linux/pci_ids.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index bebaee7edb52..67a697940471 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1551,6 +1551,7 @@ #define PCI_VENDOR_ID_ALTIMA 0x173b #define PCI_DEVICE_ID_ALTIMA_AC1000 0x03e8 +#define PCI_DEVICE_ID_ALTIMA_AC9100 0x03ea #define PCI_VENDOR_ID_SYMPHONY 0x1c1c #define PCI_DEVICE_ID_SYMPHONY_101 0x0001 -- cgit v1.2.3 From 0ed47278fbfb6f5a358fb0c5b401cc1e423ff861 Mon Sep 17 00:00:00 2001 From: Kai Germaschewski Date: Mon, 20 May 2002 12:29:51 -0500 Subject: Fix UTS_MACHINE Remove the default for UTS_MACHINE, it gets set in include/linux/compile.h, just as UTS_RELEASE. (noticed by David Gibson) --- include/linux/uts.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/uts.h b/include/linux/uts.h index 39e09ae10135..73eb1ed36ec4 100644 --- a/include/linux/uts.h +++ b/include/linux/uts.h @@ -8,10 +8,6 @@ #define UTS_SYSNAME "Linux" #endif -#ifndef UTS_MACHINE -#define UTS_MACHINE "unknown" -#endif - #ifndef UTS_NODENAME #define UTS_NODENAME "(none)" /* set by sethostname() */ #endif -- cgit v1.2.3 From 978364b96a712fa71888c5ab6f57f530d42fb418 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 20 May 2002 21:32:52 -0700 Subject: [PATCH] buffermem_pages removal (5/5) No more users of buffermem_pages are left, remove it. While at it also remove some orphaned externs around it in swap.h --- fs/buffer.c | 15 --------------- include/linux/swap.h | 4 ---- mm/page_alloc.c | 5 ----- 3 files changed, 24 deletions(-) (limited to 'include/linux') diff --git a/fs/buffer.c b/fs/buffer.c index 904fec39dd60..89f89c4e84d7 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -36,9 +36,6 @@ #define BH_ENTRY(list) list_entry((list), struct buffer_head, b_assoc_buffers) -/* This is used by some architectures to estimate available memory. */ -atomic_t buffermem_pages = ATOMIC_INIT(0); - /* * Hashed waitqueue_head's for wait_on_buffer() */ @@ -151,10 +148,6 @@ void __wait_on_buffer(struct buffer_head * bh) static inline void __set_page_buffers(struct page *page, struct buffer_head *head) { - struct inode *inode = page->mapping->host; - - if (inode && S_ISBLK(inode->i_mode)) - atomic_inc(&buffermem_pages); if (page_has_buffers(page)) buffer_error(); set_page_buffers(page, head); @@ -164,14 +157,6 @@ __set_page_buffers(struct page *page, struct buffer_head *head) static inline void __clear_page_buffers(struct page *page) { - struct address_space *mapping = page->mapping; - - if (mapping) { - struct inode *inode = mapping->host; - - if (S_ISBLK(inode->i_mode)) - atomic_dec(&buffermem_pages); - } clear_page_buffers(page); page_cache_release(page); } diff --git a/include/linux/swap.h b/include/linux/swap.h index 3a376842c21c..3d87e4334851 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -102,12 +102,8 @@ extern unsigned long totalhigh_pages; extern unsigned int nr_free_pages(void); extern unsigned int nr_free_buffer_pages(void); extern unsigned int nr_free_pagecache_pages(void); -extern unsigned long nr_buffermem_pages(void); extern int nr_active_pages; extern int nr_inactive_pages; -extern atomic_t nr_async_pages; -extern atomic_t buffermem_pages; -extern spinlock_t pagecache_lock; extern void __remove_inode_page(struct page *); /* Incomplete types for prototype declarations: */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 09d14971c2e6..82e86a0c4d9a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -569,11 +569,6 @@ unsigned int nr_free_highpages (void) } #endif -unsigned long nr_buffermem_pages(void) -{ - return atomic_read(&buffermem_pages); -} - /* * Accumulate the page_state information across all CPUs. * The result is unavoidably approximate - it can change -- cgit v1.2.3 From facdecfa750f3459f94b5b60cfd73b676fced0df Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 20 May 2002 21:36:42 -0700 Subject: [PATCH] Futex update. This changes futex semantics to a simple "sleep if this address equals this value" interface, which is more convenient for building other primitives. It also adds a timeout value. Example library can be found at: http://www.kernel.org/pub/linux/kernel/people/rusty/futex-2.0.tar.gz --- include/linux/futex.h | 4 +- kernel/futex.c | 132 +++++++++++++++++++++++++------------------------- 2 files changed, 69 insertions(+), 67 deletions(-) (limited to 'include/linux') diff --git a/include/linux/futex.h b/include/linux/futex.h index 5ebcc879b4c0..d913c30590df 100644 --- a/include/linux/futex.h +++ b/include/linux/futex.h @@ -2,7 +2,7 @@ #define _LINUX_FUTEX_H /* Second argument to futex syscall */ -#define FUTEX_UP (0) -#define FUTEX_DOWN (1) +#define FUTEX_WAIT (0) +#define FUTEX_WAKE (1) #endif diff --git a/kernel/futex.c b/kernel/futex.c index 4ef5ff0ff81b..4541b2448e49 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -32,7 +32,8 @@ #include #include #include -#include +#include +#include /* These mutexes are a very simple counter: the winner is the one who decrements from 1 to 0. The counter starts at 1 when the lock is @@ -68,22 +69,27 @@ static inline struct list_head *hash_futex(struct page *page, return &futex_queues[hash_long(h, FUTEX_HASHBITS)]; } -static inline void wake_one_waiter(struct list_head *head, - struct page *page, - unsigned int offset) +static int futex_wake(struct list_head *head, + struct page *page, + unsigned int offset, + int num) { - struct list_head *i; + struct list_head *i, *next; + int num_woken = 0; spin_lock(&futex_lock); - list_for_each(i, head) { + list_for_each_safe(i, next, head) { struct futex_q *this = list_entry(i, struct futex_q, list); if (this->page == page && this->offset == offset) { + list_del_init(i); wake_up_process(this->task); - break; + num_woken++; + if (num_woken >= num) break; } } spin_unlock(&futex_lock); + return num_woken; } /* Add at end to avoid starvation */ @@ -101,11 +107,17 @@ static inline void queue_me(struct list_head *head, spin_unlock(&futex_lock); } -static inline void unqueue_me(struct futex_q *q) +/* Return 1 if we were still queued (ie. 0 means we were woken) */ +static inline int unqueue_me(struct futex_q *q) { + int ret = 0; spin_lock(&futex_lock); - list_del(&q->list); + if (!list_empty(&q->list)) { + list_del(&q->list); + ret = 1; + } spin_unlock(&futex_lock); + return ret; } /* Get kernel address of the user page and pin it. */ @@ -129,74 +141,65 @@ static struct page *pin_page(unsigned long page_start) return page; } -/* Try to decrement the user count to zero. */ -static int decrement_to_zero(struct page *page, unsigned int offset) -{ - atomic_t *count; - int ret = 0; - - count = kmap(page) + offset; - /* If we take the semaphore from 1 to 0, it's ours. If it's - zero, decrement anyway, to indicate we are waiting. If - it's negative, don't decrement so we don't wrap... */ - if (atomic_read(count) >= 0 && atomic_dec_and_test(count)) - ret = 1; - kunmap(page); - return ret; -} - -/* Simplified from arch/ppc/kernel/semaphore.c: Paul M. is a genius. */ -static int futex_down(struct list_head *head, struct page *page, int offset) +static int futex_wait(struct list_head *head, + struct page *page, + int offset, + int val, + int *uaddr, + unsigned long time) { - int retval = 0; + int curval; struct futex_q q; + int ret = 0; - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); queue_me(head, &q, page, offset); - while (!decrement_to_zero(page, offset)) { - if (signal_pending(current)) { - retval = -EINTR; - break; - } - schedule(); - current->state = TASK_INTERRUPTIBLE; - } - current->state = TASK_RUNNING; - unqueue_me(&q); - /* If we were signalled, we might have just been woken: we - must wake another one. Otherwise we need to wake someone - else (if they are waiting) so they drop the count below 0, - and when we "up" in userspace, we know there is a - waiter. */ - wake_one_waiter(head, page, offset); - return retval; -} + /* Page is pinned, can't fail */ + if (get_user(curval, uaddr) != 0) + BUG(); -static int futex_up(struct list_head *head, struct page *page, int offset) -{ - atomic_t *count; - - count = kmap(page) + offset; - atomic_set(count, 1); - smp_wmb(); - kunmap(page); - wake_one_waiter(head, page, offset); - return 0; + if (curval != val) { + ret = -EWOULDBLOCK; + set_current_state(TASK_RUNNING); + goto out; + } + time = schedule_timeout(time); + if (time == 0) { + ret = -ETIMEDOUT; + goto out; + } + if (signal_pending(current)) { + ret = -EINTR; + goto out; + } + out: + /* Were we woken up anyway? */ + if (!unqueue_me(&q)) + return 0; + return ret; } -asmlinkage int sys_futex(void *uaddr, int op) +asmlinkage int sys_futex(void *uaddr, int op, int val, struct timespec *utime) { int ret; unsigned long pos_in_page; struct list_head *head; struct page *page; + unsigned long time = MAX_SCHEDULE_TIMEOUT; + + if (utime) { + struct timespec t; + if (copy_from_user(&t, utime, sizeof(t)) != 0) + return -EFAULT; + time = timespec_to_jiffies(&t) + 1; + } pos_in_page = ((unsigned long)uaddr) % PAGE_SIZE; /* Must be "naturally" aligned, and not on page boundary. */ - if ((pos_in_page % __alignof__(atomic_t)) != 0 - || pos_in_page + sizeof(atomic_t) > PAGE_SIZE) + if ((pos_in_page % __alignof__(int)) != 0 + || pos_in_page + sizeof(int) > PAGE_SIZE) return -EINVAL; /* Simpler if it doesn't vanish underneath us. */ @@ -206,13 +209,12 @@ asmlinkage int sys_futex(void *uaddr, int op) head = hash_futex(page, pos_in_page); switch (op) { - case FUTEX_UP: - ret = futex_up(head, page, pos_in_page); + case FUTEX_WAIT: + ret = futex_wait(head, page, pos_in_page, val, uaddr, time); break; - case FUTEX_DOWN: - ret = futex_down(head, page, pos_in_page); + case FUTEX_WAKE: + ret = futex_wake(head, page, pos_in_page, val); break; - /* Add other lock types here... */ default: ret = -EINVAL; } -- cgit v1.2.3 From 2c6e92adaa8f0bfb73dc03658ebbb49a22cc9387 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 20 May 2002 21:36:50 -0700 Subject: [PATCH] Tasklet cleanup This makes tasklet_vec and tasklet_hi_vec static inside softirq.c, and makes them __per_cpu_data. --- include/linux/interrupt.h | 8 -------- kernel/ksyms.c | 2 -- kernel/softirq.c | 45 +++++++++++++++++++++++---------------------- 3 files changed, 23 insertions(+), 32 deletions(-) (limited to 'include/linux') diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 67bce357a7a1..90446b0d75e5 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -124,14 +124,6 @@ enum TASKLET_STATE_RUN /* Tasklet is running (SMP only) */ }; -struct tasklet_head -{ - struct tasklet_struct *list; -} __attribute__ ((__aligned__(SMP_CACHE_BYTES))); - -extern struct tasklet_head tasklet_vec[NR_CPUS]; -extern struct tasklet_head tasklet_hi_vec[NR_CPUS]; - #ifdef CONFIG_SMP static inline int tasklet_trylock(struct tasklet_struct *t) { diff --git a/kernel/ksyms.c b/kernel/ksyms.c index add2ac9dd8f3..cc335bff25a1 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -568,8 +568,6 @@ EXPORT_SYMBOL(strspn); EXPORT_SYMBOL(strsep); /* software interrupts */ -EXPORT_SYMBOL(tasklet_hi_vec); -EXPORT_SYMBOL(tasklet_vec); EXPORT_SYMBOL(bh_task_vec); EXPORT_SYMBOL(init_bh); EXPORT_SYMBOL(remove_bh); diff --git a/kernel/softirq.c b/kernel/softirq.c index 5b665bd72a11..c290a1d81e12 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -16,6 +16,7 @@ #include #include #include +#include /* - No shared variables, all the data are CPU local. @@ -145,42 +146,43 @@ void open_softirq(int nr, void (*action)(struct softirq_action*), void *data) /* Tasklets */ +struct tasklet_head +{ + struct tasklet_struct *list; +}; -struct tasklet_head tasklet_vec[NR_CPUS] __cacheline_aligned_in_smp; -struct tasklet_head tasklet_hi_vec[NR_CPUS] __cacheline_aligned_in_smp; +static struct tasklet_head tasklet_vec __per_cpu_data; +static struct tasklet_head tasklet_hi_vec __per_cpu_data; void __tasklet_schedule(struct tasklet_struct *t) { - int cpu = smp_processor_id(); unsigned long flags; local_irq_save(flags); - t->next = tasklet_vec[cpu].list; - tasklet_vec[cpu].list = t; - cpu_raise_softirq(cpu, TASKLET_SOFTIRQ); + t->next = this_cpu(tasklet_vec).list; + this_cpu(tasklet_vec).list = t; + cpu_raise_softirq(smp_processor_id(), TASKLET_SOFTIRQ); local_irq_restore(flags); } void __tasklet_hi_schedule(struct tasklet_struct *t) { - int cpu = smp_processor_id(); unsigned long flags; local_irq_save(flags); - t->next = tasklet_hi_vec[cpu].list; - tasklet_hi_vec[cpu].list = t; - cpu_raise_softirq(cpu, HI_SOFTIRQ); + t->next = this_cpu(tasklet_hi_vec).list; + this_cpu(tasklet_hi_vec).list = t; + cpu_raise_softirq(smp_processor_id(), HI_SOFTIRQ); local_irq_restore(flags); } static void tasklet_action(struct softirq_action *a) { - int cpu = smp_processor_id(); struct tasklet_struct *list; local_irq_disable(); - list = tasklet_vec[cpu].list; - tasklet_vec[cpu].list = NULL; + list = this_cpu(tasklet_vec).list; + this_cpu(tasklet_vec).list = NULL; local_irq_enable(); while (list) { @@ -200,21 +202,20 @@ static void tasklet_action(struct softirq_action *a) } local_irq_disable(); - t->next = tasklet_vec[cpu].list; - tasklet_vec[cpu].list = t; - __cpu_raise_softirq(cpu, TASKLET_SOFTIRQ); + t->next = this_cpu(tasklet_vec).list; + this_cpu(tasklet_vec).list = t; + __cpu_raise_softirq(smp_processor_id(), TASKLET_SOFTIRQ); local_irq_enable(); } } static void tasklet_hi_action(struct softirq_action *a) { - int cpu = smp_processor_id(); struct tasklet_struct *list; local_irq_disable(); - list = tasklet_hi_vec[cpu].list; - tasklet_hi_vec[cpu].list = NULL; + list = this_cpu(tasklet_hi_vec).list; + this_cpu(tasklet_hi_vec).list = NULL; local_irq_enable(); while (list) { @@ -234,9 +235,9 @@ static void tasklet_hi_action(struct softirq_action *a) } local_irq_disable(); - t->next = tasklet_hi_vec[cpu].list; - tasklet_hi_vec[cpu].list = t; - __cpu_raise_softirq(cpu, HI_SOFTIRQ); + t->next = this_cpu(tasklet_hi_vec).list; + this_cpu(tasklet_hi_vec).list = t; + __cpu_raise_softirq(smp_processor_id(), HI_SOFTIRQ); local_irq_enable(); } } -- cgit v1.2.3 From 70e08a38b2ded7518678bb1f2a89862b0fa5cc1f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 20 May 2002 21:39:34 -0700 Subject: [PATCH] bfs header move around + warning fix (Patch has been ACKed by the bfs maintainer) Now that bfs no more is included in the big unions in fs.h it makes sense to move the contents of bfs_fs_i.h and bfs_fs_sb.h to a bfs-private location. I've created fs/bfs/bfs.h for that, also merging in bfs_defs.h. In addition I've changed si_imap to an unsigned long pointer as the bitops now use that type explicitly. --- fs/bfs/bfs.h | 60 +++++++++++++++++++++++++++++++++++++++++++++++ fs/bfs/bfs_defs.h | 3 --- fs/bfs/dir.c | 5 ++-- fs/bfs/file.c | 4 ++-- fs/bfs/inode.c | 6 ++--- include/linux/bfs_fs.h | 25 -------------------- include/linux/bfs_fs_i.h | 21 ----------------- include/linux/bfs_fs_sb.h | 25 -------------------- 8 files changed, 66 insertions(+), 83 deletions(-) create mode 100644 fs/bfs/bfs.h delete mode 100644 fs/bfs/bfs_defs.h delete mode 100644 include/linux/bfs_fs_i.h delete mode 100644 include/linux/bfs_fs_sb.h (limited to 'include/linux') diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h new file mode 100644 index 000000000000..48da64e58fa4 --- /dev/null +++ b/fs/bfs/bfs.h @@ -0,0 +1,60 @@ +/* + * fs/bfs/bfs.h + * Copyright (C) 1999 Tigran Aivazian + */ +#ifndef _FS_BFS_BFS_H +#define _FS_BFS_BFS_H + +#include + +/* + * BFS file system in-core superblock info + */ +struct bfs_sb_info { + unsigned long si_blocks; + unsigned long si_freeb; + unsigned long si_freei; + unsigned long si_lf_ioff; + unsigned long si_lf_sblk; + unsigned long si_lf_eblk; + unsigned long si_lasti; + unsigned long * si_imap; + struct buffer_head * si_sbh; /* buffer header w/superblock */ + struct bfs_super_block * si_bfs_sb; /* superblock in si_sbh->b_data */ +}; + +/* + * BFS file system in-core inode info + */ +struct bfs_inode_info { + unsigned long i_dsk_ino; /* inode number from the disk, can be 0 */ + unsigned long i_sblock; + unsigned long i_eblock; + struct inode vfs_inode; +}; + +static inline struct bfs_sb_info *BFS_SB(struct super_block *sb) +{ + return sb->u.generic_sbp; +} + +static inline struct bfs_inode_info *BFS_I(struct inode *inode) +{ + return list_entry(inode, struct bfs_inode_info, vfs_inode); +} + + +#define printf(format, args...) \ + printk(KERN_ERR "BFS-fs: %s(): " format, __FUNCTION__, ## args) + + +/* file.c */ +extern struct inode_operations bfs_file_inops; +extern struct file_operations bfs_file_operations; +extern struct address_space_operations bfs_aops; + +/* dir.c */ +extern struct inode_operations bfs_dir_inops; +extern struct file_operations bfs_dir_operations; + +#endif /* _FS_BFS_BFS_H */ diff --git a/fs/bfs/bfs_defs.h b/fs/bfs/bfs_defs.h deleted file mode 100644 index 207c95bdb594..000000000000 --- a/fs/bfs/bfs_defs.h +++ /dev/null @@ -1,3 +0,0 @@ -#define printf(format, args...) \ - printk(KERN_ERR "BFS-fs: %s(): " format, __FUNCTION__, ## args) - diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 5913276d8d07..0fd7d362be4d 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -6,10 +6,9 @@ #include #include -#include +#include #include - -#include "bfs_defs.h" +#include "bfs.h" #undef DEBUG diff --git a/fs/bfs/file.c b/fs/bfs/file.c index 313e5e4009ab..f0d01864f2f2 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c @@ -5,9 +5,9 @@ */ #include -#include +#include #include -#include "bfs_defs.h" +#include "bfs.h" #undef DEBUG diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index df4cf556785a..1fd0fe66134e 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -9,12 +9,10 @@ #include #include #include -#include +#include #include - #include - -#include "bfs_defs.h" +#include "bfs.h" MODULE_AUTHOR("Tigran A. Aivazian "); MODULE_DESCRIPTION("SCO UnixWare BFS filesystem for Linux"); diff --git a/include/linux/bfs_fs.h b/include/linux/bfs_fs.h index 0c6349eec459..f7f0913cd110 100644 --- a/include/linux/bfs_fs.h +++ b/include/linux/bfs_fs.h @@ -6,9 +6,6 @@ #ifndef _LINUX_BFS_FS_H #define _LINUX_BFS_FS_H -#include -#include - #define BFS_BSIZE_BITS 9 #define BFS_BSIZE (1<s_from != -1) && (bfs_sb->s_to != -1) && !(sb->s_flags & MS_RDONLY)) -#ifdef __KERNEL__ - -/* file.c */ -extern struct inode_operations bfs_file_inops; -extern struct file_operations bfs_file_operations; -extern struct address_space_operations bfs_aops; - -/* dir.c */ -extern struct inode_operations bfs_dir_inops; -extern struct file_operations bfs_dir_operations; - -static inline struct bfs_sb_info *BFS_SB(struct super_block *sb) -{ - return sb->u.generic_sbp; -} - -static inline struct bfs_inode_info *BFS_I(struct inode *inode) -{ - return list_entry(inode, struct bfs_inode_info, vfs_inode); -} - -#endif /* __KERNEL__ */ #endif /* _LINUX_BFS_FS_H */ diff --git a/include/linux/bfs_fs_i.h b/include/linux/bfs_fs_i.h deleted file mode 100644 index 5a85f1dc143f..000000000000 --- a/include/linux/bfs_fs_i.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * include/linux/bfs_fs_i.h - * Copyright (C) 1999 Tigran Aivazian - */ - -#ifndef _LINUX_BFS_FS_I -#define _LINUX_BFS_FS_I - -#include - -/* - * BFS file system in-core inode info - */ -struct bfs_inode_info { - unsigned long i_dsk_ino; /* inode number from the disk, can be 0 */ - unsigned long i_sblock; - unsigned long i_eblock; - struct inode vfs_inode; -}; - -#endif /* _LINUX_BFS_FS_I */ diff --git a/include/linux/bfs_fs_sb.h b/include/linux/bfs_fs_sb.h deleted file mode 100644 index efdc30ec7241..000000000000 --- a/include/linux/bfs_fs_sb.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * include/linux/bfs_fs_sb.h - * Copyright (C) 1999 Tigran Aivazian - */ - -#ifndef _LINUX_BFS_FS_SB -#define _LINUX_BFS_FS_SB - -/* - * BFS file system in-core superblock info - */ -struct bfs_sb_info { - unsigned long si_blocks; - unsigned long si_freeb; - unsigned long si_freei; - unsigned long si_lf_ioff; - unsigned long si_lf_sblk; - unsigned long si_lf_eblk; - unsigned long si_lasti; - char * si_imap; - struct buffer_head * si_sbh; /* buffer header w/superblock */ - struct bfs_super_block * si_bfs_sb; /* superblock in si_sbh->b_data */ -}; - -#endif /* _LINUX_BFS_FS_SB */ -- cgit v1.2.3 From ea882f08613a6efa9929b3d6a7e7bfcbec22cf92 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 20 May 2002 21:43:46 -0700 Subject: [PATCH] reiserfs 64 bit bug in get_virtual_node_size This patch fixes a problem with reiserfs on 64 bit machines. Our struct virtual_item is a different size there, and some calculations that assume otherwise lead to this panic create_virtual_node: vs-8030: create_virtual_node: virtual node space consumed --- fs/reiserfs/fix_node.c | 20 ++++++++++++-------- fs/reiserfs/item_ops.c | 7 ------- include/linux/reiserfs_fs.h | 7 +++++++ 3 files changed, 19 insertions(+), 15 deletions(-) (limited to 'include/linux') diff --git a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c index 802eefb3825d..86ac5cb83dd1 100644 --- a/fs/reiserfs/fix_node.c +++ b/fs/reiserfs/fix_node.c @@ -2011,16 +2011,20 @@ void reiserfs_kfree (const void * vp, size_t size, struct super_block * s) static int get_virtual_node_size (struct super_block * sb, struct buffer_head * bh) { - // int size = sizeof (struct virtual_item); /* for new item in case of insert */ - // int i, nr_items; - // struct item_head * ih; + int max_num_of_items; + int max_num_of_entries; + unsigned long blocksize = sb->s_blocksize; - // this is enough for _ALL_ currently possible cases. In 4 k block - // one may put < 170 empty items. Each virtual item eats 12 - // byte. The biggest direntry item may have < 256 entries. Each - // entry would eat 2 byte of virtual node space - return sb->s_blocksize; +#define MIN_NAME_LEN 1 + max_num_of_items = (blocksize - BLKH_SIZE) / (IH_SIZE + MIN_ITEM_LEN); + max_num_of_entries = (blocksize - BLKH_SIZE - IH_SIZE) / + (DEH_SIZE + MIN_NAME_LEN); + + return sizeof(struct virtual_node) + + max(max_num_of_items * sizeof (struct virtual_item), + sizeof (struct virtual_item) + sizeof(struct direntry_uarea) + + (max_num_of_entries - 1) * sizeof (__u16)); } diff --git a/fs/reiserfs/item_ops.c b/fs/reiserfs/item_ops.c index 7cf647e6f9b1..ac5c94b1500e 100644 --- a/fs/reiserfs/item_ops.c +++ b/fs/reiserfs/item_ops.c @@ -466,13 +466,6 @@ static void direntry_check_item (struct item_head * ih, char * item) #define DIRENTRY_VI_FIRST_DIRENTRY_ITEM 1 -struct direntry_uarea { - int flags; - __u16 entry_count; - __u16 entry_sizes[1]; -} __attribute__ ((__packed__)) ; - - /* * function returns old entry number in directory item in real node * using new entry number in virtual item in virtual node */ diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 173279f6ff0a..abe55b91a328 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -1342,6 +1342,13 @@ struct virtual_node struct virtual_item * vn_vi; /* array of items (including a new one, excluding item to be deleted) */ }; +/* used by directory items when creating virtual nodes */ +struct direntry_uarea { + int flags; + __u16 entry_count; + __u16 entry_sizes[1]; +} __attribute__ ((__packed__)) ; + /***************************************************************************/ /* TREE BALANCE */ -- cgit v1.2.3 From 542f96a52f55f50dae8b82e11dac096b094202f0 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 21 May 2002 01:57:49 -0700 Subject: [PATCH] suspend-to-{RAM,disk} Here's suspend-to-{RAM,disk} combined patch for 2.5.17. Suspend-to-disk is pretty stable and was tested in 2.4-ac. Suspend-to-RAM is little more experimental, but works for me, and is certainly better than disk-eating version currently in kernel. Major parts are: process stopper, S3 specific code, S4 specific code. --- Documentation/driver-model.txt | 53 +- Documentation/swsusp.txt | 159 +++++ MAINTAINERS | 8 + arch/i386/Config.help | 25 + arch/i386/boot/video.S | 1 + arch/i386/config.in | 3 + arch/i386/defconfig | 1 + arch/i386/kernel/acpi.c | 30 + arch/i386/kernel/acpi_wakeup.S | 178 +++++- arch/i386/kernel/apm.c | 1 + arch/i386/kernel/i8259.c | 15 +- arch/i386/kernel/setup.c | 5 + arch/i386/kernel/signal.c | 7 + arch/i386/kernel/time.c | 12 + arch/i386/vmlinux.lds | 6 + drivers/acpi/acpi_system.c | 38 +- drivers/block/floppy.c | 5 + drivers/block/ll_rw_blk.c | 4 +- drivers/block/loop.c | 5 +- drivers/char/sysrq.c | 21 + drivers/ide/ide-disk.c | 3 + drivers/pci/power.c | 4 +- drivers/usb/storage/usb.c | 1 + fs/buffer.c | 3 + fs/jbd/journal.c | 12 +- fs/reiserfs/journal.c | 9 +- include/asm-generic/bitops.h | 6 + include/asm-i386/bitops.h | 6 + include/asm-i386/suspend.h | 304 +++++++++ include/linux/bitops.h | 43 +- include/linux/init.h | 3 + include/linux/page-flags.h | 7 + include/linux/reboot.h | 9 + include/linux/sched.h | 5 + include/linux/suspend.h | 65 ++ include/linux/tqueue.h | 2 +- init/do_mounts.c | 6 + kernel/Makefile | 3 +- kernel/context.c | 1 + kernel/signal.c | 2 +- kernel/softirq.c | 1 + kernel/suspend.c | 1327 ++++++++++++++++++++++++++++++++++++++++ kernel/sys.c | 11 + mm/page_alloc.c | 41 ++ mm/page_io.c | 4 + mm/pdflush.c | 12 +- mm/vmscan.c | 9 +- 47 files changed, 2414 insertions(+), 62 deletions(-) create mode 100644 Documentation/swsusp.txt create mode 100644 include/asm-i386/suspend.h create mode 100644 include/linux/suspend.h create mode 100644 kernel/suspend.c (limited to 'include/linux') diff --git a/Documentation/driver-model.txt b/Documentation/driver-model.txt index d2740203568f..69f20d2d9b70 100644 --- a/Documentation/driver-model.txt +++ b/Documentation/driver-model.txt @@ -52,7 +52,8 @@ appropriate callbacks that each device (or bridge) of that type share. Each bus layer should implement the callbacks for these drivers. It then forwards the calls on to the device-specific callbacks. This means that device-specific drivers must still implement callbacks for each operation. -But, they are not called from the top level driver layer. +But, they are not called from the top level driver layer. [So for example +PCI devices will not call device_register but pci_device_register.] This does add another layer of indirection for calling one of these functions, but there are benefits that are believed to outweigh this slowdown. @@ -60,7 +61,7 @@ but there are benefits that are believed to outweigh this slowdown. First, it prevents device-specific drivers from having to know about the global device layer. This speeds up integration time incredibly. It also allows drivers to be more portable across kernel versions. Note that the -former was intentional, the latter is an added bonus. +former was intentional, the latter is an added bonus. Second, this added indirection allows the bus to perform any additional logic necessary for its child devices. A bus layer may add additional information to @@ -225,7 +226,6 @@ platform_data: It also allows the platform driver (e.g. ACPI) to a driver without the driver having to have explicit knowledge of (atrocities like) ACPI. - current_state: Current power state of the device. For PCI and other modern devices, this is 0-3, though it's not necessarily limited to those values. @@ -251,18 +251,24 @@ struct device_driver { } probe: - Check for device existence and associate driver with it. + Check for device existence and associate driver with it. In case of device + insertion, *all* drivers are called. Struct device has parent and bus_id + valid at this point. probe() may only be called from process context. Returns + 0 if it handles that device, -ESRCH if this driver does not know how to handle + this device, valid error otherwise. remove: Dissociate driver with device. Releases device so that it could be used by another driver. Also, if it is a hotplug device (hotplug PCI, Cardbus), an - ejection event could take place here. + ejection event could take place here. remove() can be called from interrupt + context. [Fixme: Is that good?] Returns 0 on success. [Can we recover from + failed remove or should I define that remove() never fails?] suspend: - Perform one step of the device suspend process. + Perform one step of the device suspend process. Returns 0 on success. resume: - Perform one step of the device resume process. + Perform one step of the device resume process. Returns 0 on success. The probe() and remove() callbacks are intended to be much simpler than the current PCI correspondents. @@ -275,7 +281,7 @@ probe() should do the following only: Some device initialisation was done in probe(). This should not be the case anymore. All initialisation should take place in the open() call for the -device. +device. [FIXME: How do you "open" uhci?] Breaking initialisation code out must also be done for the resume() callback, as most devices will have to be completely reinitialised when coming back from @@ -324,6 +330,7 @@ the stage: enum{ SUSPEND_NOTIFY, + SUSPEND_DISABLE, SUSPEND_SAVE_STATE, SUSPEND_POWER_DOWN, }; @@ -331,6 +338,7 @@ enum{ enum { RESUME_POWER_ON, RESUME_RESTORE_STATE, + RESUME_ENABLE, }; @@ -352,9 +360,9 @@ shutting down the device(s) you want to save state to. Instead, the walking of the device tree has been moved to userspace. When a user requests the system to suspend, it will walk the device tree, as exported via driverfs, and tell each device to go to sleep. It will do this multiple -times based on what the system policy is. - -[ FIXME: URL pointer to the corresponding utility is missing here! ] +times based on what the system policy is. [Not possible. Take ACPI enabled +system, with battery critically low. In such state, you want to suspend-to-disk, +*fast*. User maybe is not even running powerd (think system startup)!] Device resume should happen in the same manner when the system awakens. @@ -366,22 +374,25 @@ This level to notify the driver that it is going to sleep. If it knows that it cannot resume the hardware from the requested level, or it feels that it is too important to be put to sleep, it should return an error from this function. -It does not have to stop I/O requests or actually save state at this point. +It does not have to stop I/O requests or actually save state at this point. Called +from process context. SUSPEND_DISABLE: The driver should stop taking I/O requests at this stage. Because the save state stage happens afterwards, the driver may not want to physically disable -the device; only mark itself unavailable if possible. +the device; only mark itself unavailable if possible. Called from process +context. SUSPEND_SAVE_STATE: The driver should allocate memory and save any device state that is relevant -for the state it is going to enter. +for the state it is going to enter. Called from process context. SUSPEND_POWER_DOWN: -The driver should place the device in the power state requested. +The driver should place the device in the power state requested. May be called +from interrupt context. For resume, the stages are defined as follows: @@ -389,25 +400,27 @@ For resume, the stages are defined as follows: RESUME_POWER_ON: Devices should be powered on and reinitialised to some known working state. +Called from process context. RESUME_RESTORE_STATE: The driver should restore device state to its pre-suspend state and free any -memory allocated for its saved state. +memory allocated for its saved state. Called from process context. RESUME_ENABLE: -The device should start taking I/O requests again. +The device should start taking I/O requests again. Called from process context. Each driver does not have to implement each stage. But, it if it does -implemente a stage, it should do what is described above. It should not assume +implement a stage, it should do what is described above. It should not assume that it performed any stage previously, or that it will perform any stage -later. +later. [Really? It makes sense to support SAVE_STATE only after DISABLE]. It is quite possible that a driver can fail during the suspend process, for whatever reason. In this event, the calling process must gracefully recover -and restore everything to their states before the suspend transition began. +and restore everything to their states before the suspend transition began. +[Suspend may not fail, think battery low.] If a driver knows that it cannot suspend or resume properly, it should fail during the notify stage. Properly implemented power management schemes should diff --git a/Documentation/swsusp.txt b/Documentation/swsusp.txt new file mode 100644 index 000000000000..8412e524a18f --- /dev/null +++ b/Documentation/swsusp.txt @@ -0,0 +1,159 @@ +From kernel/suspend.c: + + * BIG FAT WARNING ********************************************************* + * + * If you have unsupported (*) devices using DMA... + * ...say goodbye to your data. + * + * If you touch anything on disk between suspend and resume... + * ...kiss your data goodbye. + * + * If your disk driver does not support suspend... (IDE does) + * ...you'd better find out how to get along + * without your data. + * + * (*) pm interface support is needed to make it safe. + +You need to append resume=/dev/your_swap_partition to kernel command +line. Then you suspend by echo 4 > /proc/acpi/sleep. + +[Notice. Rest docs is pretty outdated (see date!) It should be safe to +use swsusp on ext3/reiserfs these days.] + + +Article about goals and implementation of Software Suspend for Linux +Author: G‚ábor Kuti +Last revised: 2002-04-08 + +Idea and goals to achieve + +Nowadays it is common in several laptops that they have a suspend button. It +saves the state of the machine to a filesystem or to a partition and switches +to standby mode. Later resuming the machine the saved state is loaded back to +ram and the machine can continue its work. It has two real benefits. First we +save ourselves the time machine goes down and later boots up, energy costs +real high when running from batteries. The other gain is that we don't have to +interrupt our programs so processes that are calculating something for a long +time shouldn't need to be written interruptible. + +On desk machines the power saving function isn't as important as it is in +laptops but we really may benefit from the second one. Nowadays the number of +desk machines supporting suspend function in their APM is going up but there +are (and there will still be for a long time) machines that don't even support +APM of any kind. On the other hand it is reported that using APM's suspend +some irqs (e.g. ATA disk irq) is lost and it is annoying for the user until +the Linux kernel resets the device. + +So I started thinking about implementing Software Suspend which doesn't need +any APM support and - since it uses pretty near only high-level routines - is +supposed to be architecture independent code. + +Using the code + +The code is experimental right now - testers, extra eyes are welcome. To +compile this support into the kernel, you need CONFIG_EXPERIMENTAL, +and then CONFIG_SOFTWARE_SUSPEND in menu General Setup to be enabled. It +cannot be used as a module and I don't think it will ever be needed. + +You have two ways to use this code. The first one is if you've compiled in +sysrq support then you may press Sysrq-D to request suspend. The other way +is with a patched SysVinit (my patch is against 2.76 and available at my +home page). You might call 'swsusp' or 'shutdown -z