From: Linus Torvalds Date: Fri, 23 Nov 2007 20:25:37 +0000 (-0500) Subject: Import 2.3.7pre9 X-Git-Tag: 2.3.7pre9 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=ee5028bb5bc777aa97c90a2f2ed9dea7c3420c59;p=history.git Import 2.3.7pre9 --- diff --git a/fs/ext2/fsync.c b/fs/ext2/fsync.c index b6dd9bce6cda..8ae361e7334a 100644 --- a/fs/ext2/fsync.c +++ b/fs/ext2/fsync.c @@ -17,6 +17,9 @@ * Removed unnecessary code duplication for little endian machines * and excessive __inline__s. * Andi Kleen, 1997 + * + * Major simplications and cleanup - we only need to do the metadata, because + * we can depend on generic_block_fdatasync() to sync the data blocks. */ #include @@ -32,8 +35,8 @@ #include -#define blocksize (EXT2_BLOCK_SIZE(inode->i_sb)) -#define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb)) +#define blocksize (EXT2_BLOCK_SIZE(inode->i_sb)) +#define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb)) static int sync_indirect(struct inode * inode, u32 * block, int wait) { @@ -41,23 +44,23 @@ static int sync_indirect(struct inode * inode, u32 * block, int wait) if (!*block) return 0; - bh = get_hash_table (inode->i_dev, le32_to_cpu(*block), blocksize); + bh = get_hash_table(inode->i_dev, le32_to_cpu(*block), blocksize); if (!bh) return 0; if (wait && buffer_req(bh) && !buffer_uptodate(bh)) { - brelse (bh); + brelse(bh); return -1; } if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) { - brelse (bh); + brelse(bh); return 0; } - ll_rw_block (WRITE, 1, &bh); + ll_rw_block(WRITE, 1, &bh); bh->b_count--; return 0; } -static int sync_iblock (struct inode * inode, u32 * iblock, +static int sync_iblock(struct inode * inode, u32 * iblock, struct buffer_head ** bh, int wait) { int rc, tmp; @@ -69,51 +72,47 @@ static int sync_iblock (struct inode * inode, u32 * iblock, rc = sync_indirect(inode, iblock, wait); if (rc) return rc; - *bh = bread (inode->i_dev, tmp, blocksize); + *bh = bread(inode->i_dev, tmp, blocksize); if (!*bh) return -1; return 0; } -static int sync_dindirect (struct inode * inode, u32 * diblock, int wait) +static int sync_dindirect(struct inode * inode, u32 * diblock, int wait) { int i; struct buffer_head * dind_bh; int rc, err = 0; - rc = sync_iblock (inode, diblock, &dind_bh, wait); + rc = sync_iblock(inode, diblock, &dind_bh, wait); if (rc || !dind_bh) return rc; for (i = 0; i < addr_per_block; i++) { - rc = sync_indirect(inode, - ((u32 *) dind_bh->b_data) + i, - wait); + rc = sync_indirect(inode, ((u32 *) dind_bh->b_data) + i, wait); if (rc) err = rc; } - brelse (dind_bh); + brelse(dind_bh); return err; } -static int sync_tindirect (struct inode * inode, u32 * tiblock, int wait) +static int sync_tindirect(struct inode * inode, u32 * tiblock, int wait) { int i; struct buffer_head * tind_bh; int rc, err = 0; - rc = sync_iblock (inode, tiblock, &tind_bh, wait); + rc = sync_iblock(inode, tiblock, &tind_bh, wait); if (rc || !tind_bh) return rc; for (i = 0; i < addr_per_block; i++) { - rc = sync_dindirect(inode, - ((u32 *) tind_bh->b_data) + i, - wait); + rc = sync_dindirect(inode, ((u32 *) tind_bh->b_data) + i, wait); if (rc) err = rc; } - brelse (tind_bh); + brelse(tind_bh); return err; } @@ -137,15 +136,15 @@ int ext2_sync_file(struct file * file, struct dentry *dentry) for (wait=0; wait<=1; wait++) { - err |= sync_indirect (inode, - inode->u.ext2_i.i_data+EXT2_IND_BLOCK, + err |= sync_indirect(inode, + inode->u.ext2_i.i_data+EXT2_IND_BLOCK, + wait); + err |= sync_dindirect(inode, + inode->u.ext2_i.i_data+EXT2_DIND_BLOCK, + wait); + err |= sync_tindirect(inode, + inode->u.ext2_i.i_data+EXT2_TIND_BLOCK, wait); - err |= sync_dindirect (inode, - inode->u.ext2_i.i_data+EXT2_DIND_BLOCK, - wait); - err |= sync_tindirect (inode, - inode->u.ext2_i.i_data+EXT2_TIND_BLOCK, - wait); } skip: err |= ext2_sync_inode (inode); diff --git a/fs/proc/array.c b/fs/proc/array.c index 4e766ca2b5eb..d2ec8eae670b 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -1326,6 +1326,9 @@ static long get_root_array(char * page, int type, char **start, case PROC_IOPORTS: return get_ioport_list(page); + + case PROC_MEMORY: + return get_mem_list(page); #ifdef CONFIG_BLK_DEV_MD case PROC_MD: return get_md_status(page); diff --git a/fs/proc/root.c b/fs/proc/root.c index ee4acbd261a9..79622b022e2c 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -621,6 +621,11 @@ static struct proc_dir_entry proc_root_ioports = { S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_array_inode_operations }; +static struct proc_dir_entry proc_root_memory = { + PROC_MEMORY, 6, "memory", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations +}; static struct proc_dir_entry proc_root_cmdline = { PROC_CMDLINE, 7, "cmdline", S_IFREG | S_IRUGO, 1, 0, 0, @@ -709,6 +714,7 @@ __initfunc(void proc_root_init(void)) proc_register(&proc_root, &proc_root_fs); proc_register(&proc_root, &proc_root_dma); proc_register(&proc_root, &proc_root_ioports); + proc_register(&proc_root, &proc_root_memory); proc_register(&proc_root, &proc_root_cmdline); #ifdef CONFIG_RTC proc_register(&proc_root, &proc_root_rtc); diff --git a/include/linux/fs.h b/include/linux/fs.h index d5029c263bc1..a613816aad1b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -234,30 +234,13 @@ struct buffer_head { typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate); void init_buffer(struct buffer_head *, kdev_t, int, bh_end_io_t *, void *); -static inline int buffer_uptodate(struct buffer_head * bh) -{ - return test_bit(BH_Uptodate, &bh->b_state); -} - -static inline int buffer_dirty(struct buffer_head * bh) -{ - return test_bit(BH_Dirty, &bh->b_state); -} - -static inline int buffer_locked(struct buffer_head * bh) -{ - return test_bit(BH_Lock, &bh->b_state); -} - -static inline int buffer_req(struct buffer_head * bh) -{ - return test_bit(BH_Req, &bh->b_state); -} +#define __buffer_state(bh, state) (((bh)->b_state & (1UL << BH_##state)) != 0) -static inline int buffer_protected(struct buffer_head * bh) -{ - return test_bit(BH_Protected, &bh->b_state); -} +#define buffer_uptodate(bh) __buffer_state(bh,Uptodate) +#define buffer_dirty(bh) __buffer_state(bh,Dirty) +#define buffer_locked(bh) __buffer_state(bh,Lock) +#define buffer_req(bh) __buffer_state(bh,Req) +#define buffer_protected(bh) __buffer_state(bh,Protected) #define buffer_page(bh) (mem_map + MAP_NR((bh)->b_data)) #define touch_buffer(bh) set_bit(PG_referenced, &buffer_page(bh)->flags) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index b5eef44dd3dc..2f729f96b256 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -1,14 +1,38 @@ /* - * portio.h Definitions of routines for detecting, reserving and + * ioport.h Definitions of routines for detecting, reserving and * allocating system resources. * - * Version: 0.01 8/30/93 - * - * Author: Donald Becker (becker@super.org) + * Authors: Donald Becker (becker@cesdis.gsfc.nasa.gov) + * David Hinds (dhinds@zen.stanford.edu) */ -#ifndef _LINUX_PORTIO_H -#define _LINUX_PORTIO_H +#ifndef _LINUX_IOPORT_H +#define _LINUX_IOPORT_H + +#define RES_IO 0 +#define RES_MEM 1 + +extern void reserve_setup(char *str, int *ints); + +extern struct resource_entry *iolist, *memlist; + +extern int get_resource_list(int class, char *buf); +extern int check_resource(int class, + unsigned long from, unsigned long extent); +extern void request_resource(int class, + unsigned long from, unsigned long extent, + const char *name); +extern void release_resource(int class, + unsigned long from, unsigned long extent); +extern unsigned long occupy_resource(int class, + unsigned long base, unsigned long end, + unsigned long num, unsigned long align, + const char *name); +extern void vacate_resource(int class, + unsigned long from, unsigned long extent); + +#define get_ioport_list(buf) get_resource_list(RES_IO, buf) +#define get_mem_list(buf) get_resource_list(RES_MEM, buf) #define HAVE_PORTRESERVE /* @@ -16,20 +40,21 @@ * Once you have found you hardware, register it with request_region(). * If you unload the driver, use release_region to free ports. */ -extern void reserve_setup(char *str, int *ints); -extern int check_region(unsigned long from, unsigned long extent); -extern void request_region(unsigned long from, unsigned long extent,const char *name); -extern void release_region(unsigned long from, unsigned long extent); -extern int get_ioport_list(char *); +#define check_region(f,e) check_resource(RES_IO,f,e) +#define request_region(f,e,n) request_resource(RES_IO,f,e,n) +#define release_region(f,e) release_resource(RES_IO,f,e) +#define occupy_region(b,e,n,a,s) occupy_resource(RES_IO,b,e,n,a,s) +#define vacate_region(f,e) vacate_resource(RES_IO,f,e) -#ifdef __sparc__ -extern unsigned long occupy_region(unsigned long base, unsigned long end, - unsigned long num, unsigned int align, - const char *name); -#endif +#define HAVE_MEMRESERVE +#define check_mem_region(f,e) check_resource(RES_MEM,f,e) +#define request_mem_region(f,e,n) request_resource(RES_MEM,f,e,n) +#define release_mem_region(f,e) release_resource(RES_MEM,f,e) +#define occupy_mem_region(b,e,n,a,s) occupy_resource(RES_MEM,b,e,n,a,s) +#define vacate_mem_region(f,e) vacate_resource(RES_MEM,f,e) #define HAVE_AUTOIRQ extern void autoirq_setup(int waittime); extern int autoirq_report(int waittime); -#endif /* _LINUX_PORTIO_H */ +#endif /* _LINUX_IOPORT_H */ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 6297457d2993..5c54d05bc585 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -37,6 +37,7 @@ enum root_directory_inos { PROC_KSYMS, PROC_DMA, PROC_IOPORTS, + PROC_MEMORY, PROC_PROFILE, /* whether enabled or not */ PROC_CMDLINE, PROC_SYS, diff --git a/kernel/ksyms.c b/kernel/ksyms.c index c9742a18a98c..03c5167100ee 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -300,10 +300,12 @@ EXPORT_SYMBOL(disable_hlt); EXPORT_SYMBOL(enable_hlt); #endif -/* IO port handling */ -EXPORT_SYMBOL(check_region); -EXPORT_SYMBOL(request_region); -EXPORT_SYMBOL(release_region); +/* resource handling */ +EXPORT_SYMBOL(check_resource); +EXPORT_SYMBOL(request_resource); +EXPORT_SYMBOL(release_resource); +EXPORT_SYMBOL(occupy_resource); +EXPORT_SYMBOL(vacate_resource); /* process management */ EXPORT_SYMBOL(__wake_up); diff --git a/kernel/resource.c b/kernel/resource.c index fa607edf8a71..4c672c6b0113 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -1,10 +1,17 @@ /* * linux/kernel/resource.c * - * Copyright (C) 1995 Linus Torvalds - * David Hinds + * Copyright (C) 1995, 1999 Linus Torvalds + * David Hinds * - * Kernel io-region resource management + * Kernel resource management + * + * We now distinguish between claiming space for devices (using the + * 'occupy' and 'vacate' calls), and associating a resource with a + * device driver (with the 'request', 'release', and 'check' calls). + * A resource can be claimed even if there is no associated driver + * (by occupying with name=NULL). Vacating a resource makes it + * available for other dynamically configured devices. */ #include @@ -12,47 +19,59 @@ #include #include -#define IOTABLE_SIZE 128 +#define RSRC_TABLE_SIZE 128 -typedef struct resource_entry_t { +struct resource_entry { u_long from, num; const char *name; - struct resource_entry_t *next; -} resource_entry_t; + struct resource_entry *next; +}; -static resource_entry_t iolist = { 0, 0, "", NULL }; +struct resource_entry res_list[] = { + { 0, 0, NULL, NULL }, /* IO */ + { 0, 0, NULL, NULL } /* mem */ +}; -static resource_entry_t iotable[IOTABLE_SIZE]; +static struct resource_entry rsrc_table[RSRC_TABLE_SIZE]; /* - * This generates the report for /proc/ioports + * This generates reports for /proc/ioports and /proc/memory */ -int get_ioport_list(char *buf) +int get_resource_list(int class, char *buf) { - resource_entry_t *p; + struct resource_entry *root = &res_list[class]; + struct resource_entry *p; int len = 0; - - for (p = iolist.next; (p) && (len < 4000); p = p->next) - len += sprintf(buf+len, "%04lx-%04lx : %s\n", - p->from, p->from+p->num-1, p->name); + char *fmt = (class == RES_IO) ? + "%04lx-%04lx : %s\n" : "%08lx-%08lx : %s\n"; + + for (p = root->next; (p) && (len < 4000); p = p->next) + len += sprintf(buf+len, fmt, p->from, p->from+p->num-1, + (p->name ? p->name : "occupied")); if (p) len += sprintf(buf+len, "4K limit reached!\n"); return len; } /* - * The workhorse function: find where to put a new entry + * Basics: find a matching resource entry, or find an insertion point */ -static resource_entry_t *find_gap(resource_entry_t *root, - u_long from, u_long num) +static struct resource_entry * +find_match(struct resource_entry *root, u_long from, u_long num) { - unsigned long flags; - resource_entry_t *p; - + struct resource_entry *p; + for (p = root; p; p = p->next) + if ((p->from == from) && (p->num == num)) + return p; + return NULL; +} + +static struct resource_entry * +find_gap(struct resource_entry *root, u_long from, u_long num) +{ + struct resource_entry *p; if (from > from+num-1) return NULL; - save_flags(flags); - cli(); for (p = root; ; p = p->next) { if ((p != root) && (p->from+p->num-1 >= from)) { p = NULL; @@ -61,123 +80,147 @@ static resource_entry_t *find_gap(resource_entry_t *root, if ((p->next == NULL) || (p->next->from > from+num-1)) break; } - restore_flags(flags); return p; } /* - * Call this from the device driver to register the ioport region. + * Call this from a driver to assert ownership of a resource */ -void request_region(unsigned long from, unsigned long num, const char *name) +void request_resource(int class, unsigned long from, + unsigned long num, const char *name) { - resource_entry_t *p; + struct resource_entry *root = &res_list[class]; + struct resource_entry *p; + long flags; int i; - for (i = 0; i < IOTABLE_SIZE; i++) - if (iotable[i].num == 0) + p = find_match(root, from, num); + if (p) { + p->name = name; + return; + } + + save_flags(flags); + cli(); + for (i = 0; i < RSRC_TABLE_SIZE; i++) + if (rsrc_table[i].num == 0) break; - if (i == IOTABLE_SIZE) - printk("warning: ioport table is full\n"); + if (i == RSRC_TABLE_SIZE) + printk("warning: resource table is full\n"); else { - p = find_gap(&iolist, from, num); - if (p == NULL) + p = find_gap(root, from, num); + if (p == NULL) { + restore_flags(flags); return; - iotable[i].name = name; - iotable[i].from = from; - iotable[i].num = num; - iotable[i].next = p->next; - p->next = &iotable[i]; - return; + } + rsrc_table[i].name = name; + rsrc_table[i].from = from; + rsrc_table[i].num = num; + rsrc_table[i].next = p->next; + p->next = &rsrc_table[i]; } + restore_flags(flags); } /* - * Call this when the device driver is unloaded + * Call these when a driver is unloaded but the device remains */ -void release_region(unsigned long from, unsigned long num) +void release_resource(int class, unsigned long from, unsigned long num) { - resource_entry_t *p, *q; - - for (p = &iolist; ; p = q) { - q = p->next; - if (q == NULL) - break; - if ((q->from == from) && (q->num == num)) { - q->num = 0; - p->next = q->next; - return; - } - } + struct resource_entry *root = &res_list[class]; + struct resource_entry *p; + p = find_match(root, from, num); + if (p) p->name = NULL; } /* - * Call this to check the ioport region before probing + * Call these to check a region for conflicts before probing */ -int check_region(unsigned long from, unsigned long num) +int check_resource(int class, unsigned long from, unsigned long num) { - return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0; + struct resource_entry *root = &res_list[class]; + struct resource_entry *p; + p = find_match(root, from, num); + if (p != NULL) + return (p->name != NULL) ? -EBUSY : 0; + return (find_gap(root, from, num) == NULL) ? -EBUSY : 0; } -#ifdef __sparc__ /* Why to carry unused code on other architectures? */ /* - * This is for architectures with MMU-managed ports (sparc). + * Call this to claim a resource for a piece of hardware */ -unsigned long occupy_region(unsigned long base, unsigned long end, - unsigned long num, unsigned int align, const char *name) +unsigned long occupy_resource(int class, unsigned long base, + unsigned long end, unsigned long num, + unsigned long align, const char *name) { + struct resource_entry *root = &res_list[class]; unsigned long from = 0, till; unsigned long flags; int i; - resource_entry_t *p; /* Scanning ptr */ - resource_entry_t *p1; /* === p->next */ - resource_entry_t *s; /* Found slot */ + struct resource_entry *p, *q; - if (base > end-1) - return 0; - if (num > end - base) + if ((base > end-1) || (num > end - base)) return 0; - for (i = 0; i < IOTABLE_SIZE; i++) - if (iotable[i].num == 0) + for (i = 0; i < RSRC_TABLE_SIZE; i++) + if (rsrc_table[i].num == 0) break; - if (i == IOTABLE_SIZE) { - /* Driver prints a warning typically. */ + if (i == RSRC_TABLE_SIZE) return 0; - } save_flags(flags); cli(); /* printk("occupy: search in %08lx[%08lx] ", base, end - base); */ - s = NULL; - for (p = &iolist; p != NULL; p = p1) { - p1 = p->next; + for (p = root; p != NULL; p = q) { + q = p->next; /* Find window in list */ - from = (p->from+p->num + align-1) & ~((unsigned long)align-1); - till = (p1 == NULL)? (unsigned long) (0 - (unsigned long)align): p1->from; + from = (p->from+p->num + align-1) & ~(align-1); + till = (q == NULL) ? (0 - align) : q->from; /* printk(" %08lx:%08lx", from, till); */ /* Clip window with base and end */ if (from < base) from = base; if (till > end) till = end; /* See if result is large enougth */ - if (from < till && from + num < till) { - s = p; + if ((from < till) && (from + num < till)) break; - } } /* printk("\r\n"); */ restore_flags(flags); - if (s == NULL) + if (p == NULL) return 0; - iotable[i].name = name; - iotable[i].from = from; - iotable[i].num = num; - iotable[i].next = s->next; - s->next = &iotable[i]; + rsrc_table[i].name = name; + rsrc_table[i].from = from; + rsrc_table[i].num = num; + rsrc_table[i].next = p->next; + p->next = &rsrc_table[i]; return from; } -#endif + +/* + * Call this when a resource becomes available for other hardware + */ +void vacate_resource(int class, unsigned long from, unsigned long num) +{ + struct resource_entry *root = &res_list[class]; + struct resource_entry *p, *q; + long flags; + + save_flags(flags); + cli(); + for (p = root; ; p = q) { + q = p->next; + if (q == NULL) + break; + if ((q->from == from) && (q->num == num)) { + q->num = 0; + p->next = q->next; + break; + } + } + restore_flags(flags); +} /* Called from init/main.c to reserve IO ports. */ void __init reserve_setup(char *str, int *ints) diff --git a/mm/filemap.c b/mm/filemap.c index d8fcac02c03f..c0a17a00f595 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -359,7 +359,7 @@ static int writeout_one_page(struct page *page) bh = head; do { - if (buffer_locked(bh) || !buffer_dirty(bh)) + if (buffer_locked(bh) || !buffer_dirty(bh) || !buffer_uptodate(bh)) continue; bh->b_flushtime = 0; @@ -376,7 +376,7 @@ static int waitfor_one_page(struct page *page) bh = head; do { wait_on_buffer(bh); - if (!buffer_uptodate(bh)) + if (buffer_req(bh) && !buffer_uptodate(bh)) error = -EIO; } while ((bh = bh->b_this_page) != head); return error;