Commit ee5028bb authored by Linus Torvalds's avatar Linus Torvalds

Import 2.3.7pre9

parent 44d548e4
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
* Removed unnecessary code duplication for little endian machines * Removed unnecessary code duplication for little endian machines
* and excessive __inline__s. * and excessive __inline__s.
* Andi Kleen, 1997 * 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 <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -32,8 +35,8 @@ ...@@ -32,8 +35,8 @@
#include <linux/locks.h> #include <linux/locks.h>
#define blocksize (EXT2_BLOCK_SIZE(inode->i_sb)) #define blocksize (EXT2_BLOCK_SIZE(inode->i_sb))
#define addr_per_block (EXT2_ADDR_PER_BLOCK(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) 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) ...@@ -41,23 +44,23 @@ static int sync_indirect(struct inode * inode, u32 * block, int wait)
if (!*block) if (!*block)
return 0; 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) if (!bh)
return 0; return 0;
if (wait && buffer_req(bh) && !buffer_uptodate(bh)) { if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
brelse (bh); brelse(bh);
return -1; return -1;
} }
if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) { if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
brelse (bh); brelse(bh);
return 0; return 0;
} }
ll_rw_block (WRITE, 1, &bh); ll_rw_block(WRITE, 1, &bh);
bh->b_count--; bh->b_count--;
return 0; 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) struct buffer_head ** bh, int wait)
{ {
int rc, tmp; int rc, tmp;
...@@ -69,51 +72,47 @@ static int sync_iblock (struct inode * inode, u32 * iblock, ...@@ -69,51 +72,47 @@ static int sync_iblock (struct inode * inode, u32 * iblock,
rc = sync_indirect(inode, iblock, wait); rc = sync_indirect(inode, iblock, wait);
if (rc) if (rc)
return rc; return rc;
*bh = bread (inode->i_dev, tmp, blocksize); *bh = bread(inode->i_dev, tmp, blocksize);
if (!*bh) if (!*bh)
return -1; return -1;
return 0; 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; int i;
struct buffer_head * dind_bh; struct buffer_head * dind_bh;
int rc, err = 0; int rc, err = 0;
rc = sync_iblock (inode, diblock, &dind_bh, wait); rc = sync_iblock(inode, diblock, &dind_bh, wait);
if (rc || !dind_bh) if (rc || !dind_bh)
return rc; return rc;
for (i = 0; i < addr_per_block; i++) { for (i = 0; i < addr_per_block; i++) {
rc = sync_indirect(inode, rc = sync_indirect(inode, ((u32 *) dind_bh->b_data) + i, wait);
((u32 *) dind_bh->b_data) + i,
wait);
if (rc) if (rc)
err = rc; err = rc;
} }
brelse (dind_bh); brelse(dind_bh);
return err; 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; int i;
struct buffer_head * tind_bh; struct buffer_head * tind_bh;
int rc, err = 0; int rc, err = 0;
rc = sync_iblock (inode, tiblock, &tind_bh, wait); rc = sync_iblock(inode, tiblock, &tind_bh, wait);
if (rc || !tind_bh) if (rc || !tind_bh)
return rc; return rc;
for (i = 0; i < addr_per_block; i++) { for (i = 0; i < addr_per_block; i++) {
rc = sync_dindirect(inode, rc = sync_dindirect(inode, ((u32 *) tind_bh->b_data) + i, wait);
((u32 *) tind_bh->b_data) + i,
wait);
if (rc) if (rc)
err = rc; err = rc;
} }
brelse (tind_bh); brelse(tind_bh);
return err; return err;
} }
...@@ -137,15 +136,15 @@ int ext2_sync_file(struct file * file, struct dentry *dentry) ...@@ -137,15 +136,15 @@ int ext2_sync_file(struct file * file, struct dentry *dentry)
for (wait=0; wait<=1; wait++) for (wait=0; wait<=1; wait++)
{ {
err |= sync_indirect (inode, err |= sync_indirect(inode,
inode->u.ext2_i.i_data+EXT2_IND_BLOCK, 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); 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: skip:
err |= ext2_sync_inode (inode); err |= ext2_sync_inode (inode);
......
...@@ -1326,6 +1326,9 @@ static long get_root_array(char * page, int type, char **start, ...@@ -1326,6 +1326,9 @@ static long get_root_array(char * page, int type, char **start,
case PROC_IOPORTS: case PROC_IOPORTS:
return get_ioport_list(page); return get_ioport_list(page);
case PROC_MEMORY:
return get_mem_list(page);
#ifdef CONFIG_BLK_DEV_MD #ifdef CONFIG_BLK_DEV_MD
case PROC_MD: case PROC_MD:
return get_md_status(page); return get_md_status(page);
......
...@@ -621,6 +621,11 @@ static struct proc_dir_entry proc_root_ioports = { ...@@ -621,6 +621,11 @@ static struct proc_dir_entry proc_root_ioports = {
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations 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 = { static struct proc_dir_entry proc_root_cmdline = {
PROC_CMDLINE, 7, "cmdline", PROC_CMDLINE, 7, "cmdline",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
...@@ -709,6 +714,7 @@ __initfunc(void proc_root_init(void)) ...@@ -709,6 +714,7 @@ __initfunc(void proc_root_init(void))
proc_register(&proc_root, &proc_root_fs); proc_register(&proc_root, &proc_root_fs);
proc_register(&proc_root, &proc_root_dma); proc_register(&proc_root, &proc_root_dma);
proc_register(&proc_root, &proc_root_ioports); proc_register(&proc_root, &proc_root_ioports);
proc_register(&proc_root, &proc_root_memory);
proc_register(&proc_root, &proc_root_cmdline); proc_register(&proc_root, &proc_root_cmdline);
#ifdef CONFIG_RTC #ifdef CONFIG_RTC
proc_register(&proc_root, &proc_root_rtc); proc_register(&proc_root, &proc_root_rtc);
......
...@@ -234,30 +234,13 @@ struct buffer_head { ...@@ -234,30 +234,13 @@ struct buffer_head {
typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate); 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 *); void init_buffer(struct buffer_head *, kdev_t, int, bh_end_io_t *, void *);
static inline int buffer_uptodate(struct buffer_head * bh) #define __buffer_state(bh, state) (((bh)->b_state & (1UL << BH_##state)) != 0)
{
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);
}
static inline int buffer_protected(struct buffer_head * bh) #define buffer_uptodate(bh) __buffer_state(bh,Uptodate)
{ #define buffer_dirty(bh) __buffer_state(bh,Dirty)
return test_bit(BH_Protected, &bh->b_state); #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 buffer_page(bh) (mem_map + MAP_NR((bh)->b_data))
#define touch_buffer(bh) set_bit(PG_referenced, &buffer_page(bh)->flags) #define touch_buffer(bh) set_bit(PG_referenced, &buffer_page(bh)->flags)
......
/* /*
* portio.h Definitions of routines for detecting, reserving and * ioport.h Definitions of routines for detecting, reserving and
* allocating system resources. * allocating system resources.
* *
* Version: 0.01 8/30/93 * Authors: Donald Becker (becker@cesdis.gsfc.nasa.gov)
* * David Hinds (dhinds@zen.stanford.edu)
* Author: Donald Becker (becker@super.org)
*/ */
#ifndef _LINUX_PORTIO_H #ifndef _LINUX_IOPORT_H
#define _LINUX_PORTIO_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 #define HAVE_PORTRESERVE
/* /*
...@@ -16,20 +40,21 @@ ...@@ -16,20 +40,21 @@
* Once you have found you hardware, register it with request_region(). * Once you have found you hardware, register it with request_region().
* If you unload the driver, use release_region to free ports. * If you unload the driver, use release_region to free ports.
*/ */
extern void reserve_setup(char *str, int *ints); #define check_region(f,e) check_resource(RES_IO,f,e)
extern int check_region(unsigned long from, unsigned long extent); #define request_region(f,e,n) request_resource(RES_IO,f,e,n)
extern void request_region(unsigned long from, unsigned long extent,const char *name); #define release_region(f,e) release_resource(RES_IO,f,e)
extern void release_region(unsigned long from, unsigned long extent); #define occupy_region(b,e,n,a,s) occupy_resource(RES_IO,b,e,n,a,s)
extern int get_ioport_list(char *); #define vacate_region(f,e) vacate_resource(RES_IO,f,e)
#ifdef __sparc__ #define HAVE_MEMRESERVE
extern unsigned long occupy_region(unsigned long base, unsigned long end, #define check_mem_region(f,e) check_resource(RES_MEM,f,e)
unsigned long num, unsigned int align, #define request_mem_region(f,e,n) request_resource(RES_MEM,f,e,n)
const char *name); #define release_mem_region(f,e) release_resource(RES_MEM,f,e)
#endif #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 #define HAVE_AUTOIRQ
extern void autoirq_setup(int waittime); extern void autoirq_setup(int waittime);
extern int autoirq_report(int waittime); extern int autoirq_report(int waittime);
#endif /* _LINUX_PORTIO_H */ #endif /* _LINUX_IOPORT_H */
...@@ -37,6 +37,7 @@ enum root_directory_inos { ...@@ -37,6 +37,7 @@ enum root_directory_inos {
PROC_KSYMS, PROC_KSYMS,
PROC_DMA, PROC_DMA,
PROC_IOPORTS, PROC_IOPORTS,
PROC_MEMORY,
PROC_PROFILE, /* whether enabled or not */ PROC_PROFILE, /* whether enabled or not */
PROC_CMDLINE, PROC_CMDLINE,
PROC_SYS, PROC_SYS,
......
...@@ -300,10 +300,12 @@ EXPORT_SYMBOL(disable_hlt); ...@@ -300,10 +300,12 @@ EXPORT_SYMBOL(disable_hlt);
EXPORT_SYMBOL(enable_hlt); EXPORT_SYMBOL(enable_hlt);
#endif #endif
/* IO port handling */ /* resource handling */
EXPORT_SYMBOL(check_region); EXPORT_SYMBOL(check_resource);
EXPORT_SYMBOL(request_region); EXPORT_SYMBOL(request_resource);
EXPORT_SYMBOL(release_region); EXPORT_SYMBOL(release_resource);
EXPORT_SYMBOL(occupy_resource);
EXPORT_SYMBOL(vacate_resource);
/* process management */ /* process management */
EXPORT_SYMBOL(__wake_up); EXPORT_SYMBOL(__wake_up);
......
/* /*
* linux/kernel/resource.c * linux/kernel/resource.c
* *
* Copyright (C) 1995 Linus Torvalds * Copyright (C) 1995, 1999 Linus Torvalds
* David Hinds * 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 <linux/sched.h> #include <linux/sched.h>
...@@ -12,47 +19,59 @@ ...@@ -12,47 +19,59 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/init.h> #include <linux/init.h>
#define IOTABLE_SIZE 128 #define RSRC_TABLE_SIZE 128
typedef struct resource_entry_t { struct resource_entry {
u_long from, num; u_long from, num;
const char *name; const char *name;
struct resource_entry_t *next; struct resource_entry *next;
} resource_entry_t; };
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; int len = 0;
char *fmt = (class == RES_IO) ?
for (p = iolist.next; (p) && (len < 4000); p = p->next) "%04lx-%04lx : %s\n" : "%08lx-%08lx : %s\n";
len += sprintf(buf+len, "%04lx-%04lx : %s\n",
p->from, p->from+p->num-1, p->name); 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) if (p)
len += sprintf(buf+len, "4K limit reached!\n"); len += sprintf(buf+len, "4K limit reached!\n");
return len; 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, static struct resource_entry *
u_long from, u_long num) find_match(struct resource_entry *root, u_long from, u_long num)
{ {
unsigned long flags; struct resource_entry *p;
resource_entry_t *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) if (from > from+num-1)
return NULL; return NULL;
save_flags(flags);
cli();
for (p = root; ; p = p->next) { for (p = root; ; p = p->next) {
if ((p != root) && (p->from+p->num-1 >= from)) { if ((p != root) && (p->from+p->num-1 >= from)) {
p = NULL; p = NULL;
...@@ -61,123 +80,147 @@ static resource_entry_t *find_gap(resource_entry_t *root, ...@@ -61,123 +80,147 @@ static resource_entry_t *find_gap(resource_entry_t *root,
if ((p->next == NULL) || (p->next->from > from+num-1)) if ((p->next == NULL) || (p->next->from > from+num-1))
break; break;
} }
restore_flags(flags);
return p; 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; int i;
for (i = 0; i < IOTABLE_SIZE; i++) p = find_match(root, from, num);
if (iotable[i].num == 0) 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; break;
if (i == IOTABLE_SIZE) if (i == RSRC_TABLE_SIZE)
printk("warning: ioport table is full\n"); printk("warning: resource table is full\n");
else { else {
p = find_gap(&iolist, from, num); p = find_gap(root, from, num);
if (p == NULL) if (p == NULL) {
restore_flags(flags);
return; return;
iotable[i].name = name; }
iotable[i].from = from; rsrc_table[i].name = name;
iotable[i].num = num; rsrc_table[i].from = from;
iotable[i].next = p->next; rsrc_table[i].num = num;
p->next = &iotable[i]; rsrc_table[i].next = p->next;
return; 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; struct resource_entry *root = &res_list[class];
struct resource_entry *p;
for (p = &iolist; ; p = q) { p = find_match(root, from, num);
q = p->next; if (p) p->name = NULL;
if (q == NULL)
break;
if ((q->from == from) && (q->num == num)) {
q->num = 0;
p->next = q->next;
return;
}
}
} }
/* /*
* 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 occupy_resource(int class, unsigned long base,
unsigned long num, unsigned int align, const char *name) 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 from = 0, till;
unsigned long flags; unsigned long flags;
int i; int i;
resource_entry_t *p; /* Scanning ptr */ struct resource_entry *p, *q;
resource_entry_t *p1; /* === p->next */
resource_entry_t *s; /* Found slot */
if (base > end-1) if ((base > end-1) || (num > end - base))
return 0;
if (num > end - base)
return 0; return 0;
for (i = 0; i < IOTABLE_SIZE; i++) for (i = 0; i < RSRC_TABLE_SIZE; i++)
if (iotable[i].num == 0) if (rsrc_table[i].num == 0)
break; break;
if (i == IOTABLE_SIZE) { if (i == RSRC_TABLE_SIZE)
/* Driver prints a warning typically. */
return 0; return 0;
}
save_flags(flags); save_flags(flags);
cli(); cli();
/* printk("occupy: search in %08lx[%08lx] ", base, end - base); */ /* printk("occupy: search in %08lx[%08lx] ", base, end - base); */
s = NULL; for (p = root; p != NULL; p = q) {
for (p = &iolist; p != NULL; p = p1) { q = p->next;
p1 = p->next;
/* Find window in list */ /* Find window in list */
from = (p->from+p->num + align-1) & ~((unsigned long)align-1); from = (p->from+p->num + align-1) & ~(align-1);
till = (p1 == NULL)? (unsigned long) (0 - (unsigned long)align): p1->from; till = (q == NULL) ? (0 - align) : q->from;
/* printk(" %08lx:%08lx", from, till); */ /* printk(" %08lx:%08lx", from, till); */
/* Clip window with base and end */ /* Clip window with base and end */
if (from < base) from = base; if (from < base) from = base;
if (till > end) till = end; if (till > end) till = end;
/* See if result is large enougth */ /* See if result is large enougth */
if (from < till && from + num < till) { if ((from < till) && (from + num < till))
s = p;
break; break;
}
} }
/* printk("\r\n"); */ /* printk("\r\n"); */
restore_flags(flags); restore_flags(flags);
if (s == NULL) if (p == NULL)
return 0; return 0;
iotable[i].name = name; rsrc_table[i].name = name;
iotable[i].from = from; rsrc_table[i].from = from;
iotable[i].num = num; rsrc_table[i].num = num;
iotable[i].next = s->next; rsrc_table[i].next = p->next;
s->next = &iotable[i]; p->next = &rsrc_table[i];
return from; 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. */ /* Called from init/main.c to reserve IO ports. */
void __init reserve_setup(char *str, int *ints) void __init reserve_setup(char *str, int *ints)
......
...@@ -359,7 +359,7 @@ static int writeout_one_page(struct page *page) ...@@ -359,7 +359,7 @@ static int writeout_one_page(struct page *page)
bh = head; bh = head;
do { do {
if (buffer_locked(bh) || !buffer_dirty(bh)) if (buffer_locked(bh) || !buffer_dirty(bh) || !buffer_uptodate(bh))
continue; continue;
bh->b_flushtime = 0; bh->b_flushtime = 0;
...@@ -376,7 +376,7 @@ static int waitfor_one_page(struct page *page) ...@@ -376,7 +376,7 @@ static int waitfor_one_page(struct page *page)
bh = head; bh = head;
do { do {
wait_on_buffer(bh); wait_on_buffer(bh);
if (!buffer_uptodate(bh)) if (buffer_req(bh) && !buffer_uptodate(bh))
error = -EIO; error = -EIO;
} while ((bh = bh->b_this_page) != head); } while ((bh = bh->b_this_page) != head);
return error; return error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment