Commit 1018aab0 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.59

parent f59dfe26
VERSION = 2
PATCHLEVEL = 1
SUBLEVEL = 58
SUBLEVEL = 59
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
......
......@@ -37,6 +37,18 @@
# error Unable to handle more than 64 irq levels.
#endif
/* PROBE_MASK is the bitset of irqs that we consider for autoprobing: */
#if defined(CONFIG_ALPHA_P2K)
/* always mask out unused timer irq 0 and RTC irq 8 */
# define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~0x101UL)
#elif defined(CONFIG_ALPHA_ALCOR)
/* always mask out unused timer irq 0, "irqs" 20-30, and the EISA cascade: */
# define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~0xfff000000001UL)
#else
/* always mask out unused timer irq 0: */
# define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~1UL)
#endif
/* Reserved interrupts. These must NEVER be requested by any driver!
*/
#define IS_RESERVED_IRQ(irq) ((irq)==2) /* IRQ 2 used by hw cascade */
......@@ -644,10 +656,13 @@ unsigned long probe_irq_on(void)
unsigned int i;
for (i = NR_IRQS - 1; i > 0; i--) {
if (!(PROBE_MASK & (1UL << i))) {
continue;
}
action = irq_action[i];
if (!action) {
enable_irq(i);
irqs |= (1 << i);
irqs |= (1UL << i);
}
}
/*
......@@ -668,14 +683,10 @@ unsigned long probe_irq_on(void)
*/
int probe_irq_off(unsigned long irqs)
{
unsigned long delay;
int i;
/* as irq 0 & 8 handling don't use this function, i didn't
* bother changing the following: */
irqs &= irq_mask & ~1; /* always mask out irq 0---it's the unused timer */
#ifdef CONFIG_ALPHA_P2K
irqs &= ~(1 << 8); /* mask out irq 8 since that's the unused RTC input to PIC */
#endif
irqs &= irq_mask;
if (!irqs)
return 0;
i = ffz(~irqs);
......
......@@ -63,6 +63,7 @@ EXPORT_SYMBOL(__global_restore_flags);
#ifdef CONFIG_MCA
/* Adapter probing and info methods. */
EXPORT_SYMBOL(machine_id);
EXPORT_SYMBOL(mca_find_adapter);
EXPORT_SYMBOL(mca_write_pos);
EXPORT_SYMBOL(mca_read_pos);
......
......@@ -176,7 +176,7 @@ static int try_to_identify (ide_drive_t *drive, byte cmd)
int rc;
ide_ioreg_t hd_status;
unsigned long timeout;
int irqs = 0;
unsigned long irqs = 0;
if (!HWIF(drive)->irq) { /* already got an IRQ? */
probe_irq_off(probe_irq_on()); /* clear dangling irqs */
......@@ -235,7 +235,7 @@ static int try_to_identify (ide_drive_t *drive, byte cmd)
(void) GET_STAT(); /* clear drive IRQ */
} else { /* Mmmm.. multiple IRQs.. don't know which was ours */
printk("%s: IRQ probe failed (%d)\n", drive->name, irqs);
printk("%s: IRQ probe failed (%ld)\n", drive->name, irqs);
#ifdef CONFIG_BLK_DEV_CMD640
#ifdef CMD640_DUMP_REGS
if (HWIF(drive)->chipset == ide_cmd640) {
......
......@@ -46,8 +46,8 @@ extern void ei_interrupt(int irq, void *dev_id, struct pt_regs *regs);
#ifndef HAVE_AUTOIRQ
/* From auto_irq.c */
extern struct device *irq2dev_map[16];
extern int autoirq_setup(int waittime);
extern int autoirq_report(int waittime);
extern void autoirq_setup(int waittime);
extern unsigned long autoirq_report(int waittime);
#endif
/* Most of these entries should be in 'struct device' (or most of the
......
......@@ -39,76 +39,18 @@ static const char *version=
#include <asm/irq.h>
#include <linux/netdevice.h>
struct device *irq2dev_map[16] = {0, 0, /* ... zeroed */};
struct device *irq2dev_map[NR_IRQS] = {0, 0, /* ... zeroed */};
unsigned long irqs_busy = 0x2147; /* The set of fixed IRQs (keyboard, timer, etc) */
unsigned long irqs_used = 0x0001; /* The set of fixed IRQs sometimes enabled. */
unsigned long irqs_reserved = 0x0000; /* An advisory "reserved" table. */
unsigned long irqs_shared = 0x0000; /* IRQ lines "shared" among conforming cards.*/
static unsigned long irqs;
static volatile unsigned long irq_bitmap; /* The irqs we actually found. */
static unsigned long irq_handled; /* The irq lines we have a handler on. */
static volatile int irq_number; /* The latest irq number we actually found. */
static void autoirq_probe(int irq, void *dev_id, struct pt_regs * regs)
void autoirq_setup(int waittime)
{
irq_number = irq;
set_bit(irq, (void *)&irq_bitmap); /* irq_bitmap |= 1 << irq; */
disable_irq(irq);
return;
}
int autoirq_setup(int waittime)
{
int i, mask;
int timeout = jiffies + waittime;
int boguscount = (waittime*loops_per_sec) / 100;
irq_handled = 0;
for (i = 0; i < 16; i++) {
if (test_bit(i, &irqs_busy) == 0
&& request_irq(i, autoirq_probe, SA_INTERRUPT, "irq probe", NULL) == 0)
set_bit(i, (void *)&irq_handled); /* irq_handled |= 1 << i;*/
}
/* Update our USED lists. */
irqs_used |= ~irq_handled;
irq_number = 0;
irq_bitmap = 0;
/* Hang out at least <waittime> jiffies waiting for bogus IRQ hits. */
while (timeout > jiffies && --boguscount > 0)
;
for (i = 0, mask = 0x01; i < 16; i++, mask <<= 1) {
if (irq_bitmap & irq_handled & mask) {
irq_handled &= ~mask;
#ifdef notdef
printk(" Spurious interrupt on IRQ %d\n", i);
#endif
free_irq(i, NULL);
}
}
return irq_handled;
irqs = probe_irq_on();
}
int autoirq_report(int waittime)
{
int i;
int timeout = jiffies+waittime;
int boguscount = (waittime*loops_per_sec) / 100;
/* Hang out at least <waittime> jiffies waiting for the IRQ. */
while (timeout > jiffies && --boguscount > 0)
if (irq_number)
break;
/* Retract the irq handlers that we installed. */
for (i = 0; i < 16; i++) {
if (test_bit(i, (void *)&irq_handled))
free_irq(i, NULL);
}
return irq_number;
return probe_irq_off(irqs);
}
/*
......
......@@ -42,6 +42,7 @@ static const char *version =
#include <linux/pci.h>
#include <linux/bios32.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/system.h>
#include <asm/io.h>
......@@ -408,6 +409,7 @@ __initfunc(static int ne_probe1(struct device *dev, int ioaddr))
outb_p(0x00, ioaddr + EN0_RCNTLO);
outb_p(0x00, ioaddr + EN0_RCNTHI);
outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
udelay(10000); /* wait 10ms for interrupt to propagate */
outb_p(0x00, ioaddr + EN0_IMR); /* Mask it again. */
dev->irq = autoirq_report(0);
if (ei_debug > 2)
......
......@@ -82,7 +82,10 @@ if [ "$CONFIG_PCI" = "y" -a "$CONFIG_SCSI_NCR53C7xx" != "y" ]; then
fi
fi
if [ "$CONFIG_MCA" = "y" ]; then
dep_tristate 'IBMMCA SCSI support' CONFIG_SCSI_IBMMCA $CONFIG_SCSI
dep_tristate 'IBMMCA SCSI support' CONFIG_SCSI_IBMMCA $CONFIG_SCSI
if [ "$CONFIG_SCSI_IBMMCA" != "n" ]; then
bool ' reset SCSI-devices while booting' SCSI_IBMMCA_DEV_RESET
fi
fi
if [ "$CONFIG_PARPORT" != "n" ]; then
dep_tristate 'IOMEGA Parallel Port ZIP drive SCSI support' CONFIG_SCSI_PPA $CONFIG_SCSI $CONFIG_PARPORT
......
This diff is collapsed.
#ifndef _IBMMCA_H
#define _IBMMCA_H
/*
/*
* Low Level Driver for the IBM Microchannel SCSI Subsystem
*/
/*services provided to the higher level of Linux SCSI driver */
int ibmmca_proc_info (char *, char **, off_t, int, int, int);
int ibmmca_detect (Scsi_Host_Template *);
int ibmmca_release (struct Scsi_Host *);
int ibmmca_command (Scsi_Cmnd *);
......@@ -21,9 +21,9 @@ extern struct proc_dir_entry proc_scsi_ibmmca;
/*initialization for Scsi_host_template type */
#define IBMMCA { \
NULL, /*next*/ \
NULL, /*module*/ \
NULL, /*usage_count*/ \
&proc_scsi_ibmmca, /*proc_dir*/ \
NULL, /*proc info fn*/ \
ibmmca_proc_info, /*proc info fn*/ \
"IBMMCA", /*name*/ \
ibmmca_detect, /*detect fn*/ \
ibmmca_release, /*release fn*/ \
......
......@@ -216,7 +216,7 @@ static int ncp_readdir(struct file *filp,
int result = 0;
int i = 0;
int index = 0;
struct inode *inode = file->f_dentry->d_inode;
struct inode *inode = filp->f_dentry->d_inode;
struct ncp_dirent *entry = NULL;
struct ncp_server *server = NCP_SERVER(inode);
struct ncp_inode_info *dir = NCP_INOP(inode);
......
......@@ -180,7 +180,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto again;
}
if (ismydir && cache->mtime != NFS_OLDMTIME(inode))
if (ismydir && cache->mtime != inode->i_mtime)
cache->valid = 0;
if (!cache->valid || cache->age < dead) {
......@@ -207,7 +207,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (j < cache->size - 1) {
index = j + 1;
entry = this_ent + 3;
} else if (*(this_ent+2) >> 16) {
} else if (*(this_ent+2) & (1 << 15)) {
/* eof */
return 0;
}
......@@ -253,7 +253,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
cache->valid = 1;
entry = cache->entry + (index = 0);
}
cache->mtime = NFS_OLDMTIME(inode);
cache->mtime = inode->i_mtime;
cache->age = jiffies;
/*
......@@ -929,99 +929,6 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
return error;
}
/*
* Many nfs protocol calls return the new file attributes after
* an operation. Here we update the inode to reflect the state
* of the server's inode.
*/
int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
{
int error = -EIO;
dfprintk(VFS, "NFS: refresh_inode(%x/%ld ct=%d)\n",
inode->i_dev, inode->i_ino, inode->i_count);
if (!inode || !fattr) {
printk("nfs_refresh_inode: inode or fattr is NULL\n");
goto out;
}
if (inode->i_ino != fattr->fileid) {
printk("nfs_refresh_inode: inode number mismatch\n");
goto out;
}
/*
* Check whether the mode has been set, as we only want to
* do this once. (We don't allow inodes to change types.)
*/
if (inode->i_mode == 0) {
inode->i_mode = fattr->mode;
if (S_ISREG(inode->i_mode))
inode->i_op = &nfs_file_inode_operations;
else if (S_ISDIR(inode->i_mode))
inode->i_op = &nfs_dir_inode_operations;
else if (S_ISLNK(inode->i_mode))
inode->i_op = &nfs_symlink_inode_operations;
else if (S_ISCHR(inode->i_mode)) {
inode->i_op = &chrdev_inode_operations;
inode->i_rdev = to_kdev_t(fattr->rdev);
} else if (S_ISBLK(inode->i_mode)) {
inode->i_op = &blkdev_inode_operations;
inode->i_rdev = to_kdev_t(fattr->rdev);
} else if (S_ISFIFO(inode->i_mode))
init_fifo(inode);
else
inode->i_op = NULL;
} else if ((inode->i_mode & S_IFMT) == (fattr->mode & S_IFMT)) {
inode->i_mode = fattr->mode;
} else {
mode_t old_mode;
/*
* Big trouble! The inode has become a different object.
*/
#if 1
printk("nfs_refresh_inode: mode changed, %07o to %07o\n",
inode->i_mode, fattr->mode);
#endif
old_mode = inode->i_mode; /* save mode */
make_bad_inode(inode);
inode->i_mode = old_mode; /* restore mode */
inode->i_nlink = 0;
/*
* No need to worry about unhashing the dentry, as the
* lookup validation will know that the inode is bad.
* (But we do want to invalidate the caches.)
*/
invalidate_inode_pages(inode);
nfs_invalidate_dircache(inode);
goto out;
}
inode->i_nlink = fattr->nlink;
inode->i_uid = fattr->uid;
inode->i_gid = fattr->gid;
/* Size changed from outside: invalidate caches on next read */
if (inode->i_size != fattr->size) {
dfprintk(PAGECACHE, "NFS: cacheinv(%x/%ld)\n",
inode->i_dev, inode->i_ino);
NFS_CACHEINV(inode);
}
if (NFS_OLDMTIME(inode) != fattr->mtime.seconds) {
dfprintk(PAGECACHE, "NFS: mtime change on %x/%ld\n",
inode->i_dev, inode->i_ino);
NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
}
inode->i_size = fattr->size;
inode->i_blocks = fattr->blocks;
inode->i_atime = fattr->atime.seconds;
inode->i_mtime = fattr->mtime.seconds;
inode->i_ctime = fattr->ctime.seconds;
error = 0;
out:
return error;
}
/*
* Local variables:
* version-control: t
......
......@@ -33,6 +33,7 @@
#include <asm/uaccess.h>
#define NFSDBG_FACILITY NFSDBG_VFS
#define NFS_PARANOIA 1
extern void nfs_invalidate_dircache_sb(struct super_block *);
......@@ -72,6 +73,7 @@ nfs_read_inode(struct inode * inode)
inode->i_rdev = 0;
inode->i_op = NULL;
NFS_CACHEINV(inode);
NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
}
static void
......@@ -356,14 +358,48 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle,
printk("nfs_fhget: iget failed\n");
return NULL;
}
if (inode->i_dev == sb->s_dev) {
if (inode->i_ino != fattr->fileid) {
printk("nfs_fhget: unexpected inode from iget\n");
return inode;
}
*NFS_FH(inode) = *fhandle;
nfs_refresh_inode(inode, fattr);
#ifdef NFS_PARANOIA
if (inode->i_dev != sb->s_dev)
printk("nfs_fhget: impossible\n");
#endif
if (inode->i_ino != fattr->fileid) {
printk("nfs_fhget: unexpected inode from iget\n");
return inode;
}
/*
* Check whether the mode has been set, as we only want to
* do this once. (We don't allow inodes to change types.)
*/
if (inode->i_mode == 0) {
inode->i_mode = fattr->mode;
if (S_ISREG(inode->i_mode))
inode->i_op = &nfs_file_inode_operations;
else if (S_ISDIR(inode->i_mode))
inode->i_op = &nfs_dir_inode_operations;
else if (S_ISLNK(inode->i_mode))
inode->i_op = &nfs_symlink_inode_operations;
else if (S_ISCHR(inode->i_mode)) {
inode->i_op = &chrdev_inode_operations;
inode->i_rdev = to_kdev_t(fattr->rdev);
} else if (S_ISBLK(inode->i_mode)) {
inode->i_op = &blkdev_inode_operations;
inode->i_rdev = to_kdev_t(fattr->rdev);
} else if (S_ISFIFO(inode->i_mode))
init_fifo(inode);
else
inode->i_op = NULL;
/*
* Preset the size and mtime, as there's no need
* to invalidate the caches.
*/
inode->i_size = fattr->size;
inode->i_mtime = fattr->mtime.seconds;
NFS_OLDMTIME(inode) = fattr->mtime.seconds;
}
*NFS_FH(inode) = *fhandle;
nfs_refresh_inode(inode, fattr);
dprintk("NFS: fhget(%x/%ld ct=%d)\n",
inode->i_dev, inode->i_ino,
inode->i_count);
......@@ -378,6 +414,17 @@ nfs_notify_change(struct inode *inode, struct iattr *attr)
struct nfs_fattr fattr;
int error;
/*
* Make sure the inode is up-to-date.
*/
error = nfs_revalidate(inode);
if (error) {
#ifdef NFS_PARANOIA
printk("nfs_notify_change: revalidate failed, error=%d\n", error);
#endif
goto out;
}
sattr.mode = (u32) -1;
if (attr->ia_valid & ATTR_MODE)
sattr.mode = attr->ia_mode;
......@@ -390,7 +437,6 @@ nfs_notify_change(struct inode *inode, struct iattr *attr)
if (attr->ia_valid & ATTR_GID)
sattr.gid = attr->ia_gid;
sattr.size = (u32) -1;
if ((attr->ia_valid & ATTR_SIZE) && S_ISREG(inode->i_mode))
sattr.size = attr->ia_size;
......@@ -408,11 +454,25 @@ nfs_notify_change(struct inode *inode, struct iattr *attr)
}
error = nfs_proc_setattr(NFS_SERVER(inode), NFS_FH(inode),
&sattr, &fattr);
if (!error) {
&sattr, &fattr);
if (error)
goto out;
/*
* If we changed the size or mtime, update the inode
* now to avoid invalidating the page cache.
*/
if (sattr.size != (u32) -1) {
if (sattr.size != fattr.size)
printk("nfs_notify_change: sattr=%d, fattr=%d??\n",
sattr.size, fattr.size);
nfs_truncate_dirty_pages(inode, sattr.size);
nfs_refresh_inode(inode, &fattr);
inode->i_size = sattr.size;
inode->i_mtime = fattr.mtime.seconds;
}
if (sattr.mtime.seconds != (u32) -1)
inode->i_mtime = fattr.mtime.seconds;
error = nfs_refresh_inode(inode, &fattr);
out:
return error;
}
......@@ -428,56 +488,154 @@ nfs_revalidate(struct inode *inode)
/*
* This function is called whenever some part of NFS notices that
* the cached attributes have to be refreshed.
*
* This is a bit tricky because we have to make sure all dirty pages
* have been sent off to the server before calling invalidate_inode_pages.
* To make sure no other process adds more write requests while we try
* our best to flush them, we make them sleep during the attribute refresh.
*
* A very similar scenario holds for the dir cache.
*/
int
_nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
{
struct nfs_fattr fattr;
int status;
int status = 0;
if (jiffies - NFS_READTIME(inode) < NFS_ATTRTIMEO(inode))
return 0;
goto out;
dfprintk(PAGECACHE, "NFS: revalidating %x/%ld inode\n",
inode->i_dev, inode->i_ino);
NFS_READTIME(inode) = jiffies;
if ((status = nfs_proc_getattr(server, NFS_FH(inode), &fattr)) < 0)
status = nfs_proc_getattr(server, NFS_FH(inode), &fattr);
if (status) {
#ifdef NFS_PARANOIA
printk("nfs_revalidate_inode: getattr failed, error=%d\n", status);
#endif
goto done;
}
nfs_refresh_inode(inode, &fattr);
if (fattr.mtime.seconds != NFS_OLDMTIME(inode)) {
if (!S_ISDIR(inode->i_mode)) {
/* This sends off all dirty pages off to the server.
* Note that this function must not sleep. */
nfs_invalidate_pages(inode);
invalidate_inode_pages(inode);
} else {
nfs_invalidate_dircache(inode);
}
NFS_OLDMTIME(inode) = fattr.mtime.seconds;
NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
} else {
status = nfs_refresh_inode(inode, &fattr);
if (status)
goto done;
if (fattr.mtime.seconds == NFS_OLDMTIME(inode)) {
/* Update attrtimeo value */
if ((NFS_ATTRTIMEO(inode) <<= 1) > NFS_MAXATTRTIMEO(inode))
NFS_ATTRTIMEO(inode) = NFS_MAXATTRTIMEO(inode);
}
status = 0;
NFS_OLDMTIME(inode) = fattr.mtime.seconds;
done:
dfprintk(PAGECACHE,
"NFS: inode %x/%ld revalidation complete (status %d).\n",
inode->i_dev, inode->i_ino, status);
out:
return status;
}
/*
* Many nfs protocol calls return the new file attributes after
* an operation. Here we update the inode to reflect the state
* of the server's inode.
*
* This is a bit tricky because we have to make sure all dirty pages
* have been sent off to the server before calling invalidate_inode_pages.
* To make sure no other process adds more write requests while we try
* our best to flush them, we make them sleep during the attribute refresh.
*
* A very similar scenario holds for the dir cache.
*/
int
nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
{
int invalid = 0;
int error = -EIO;
dfprintk(VFS, "NFS: refresh_inode(%x/%ld ct=%d)\n",
inode->i_dev, inode->i_ino, inode->i_count);
if (!inode || !fattr) {
printk("nfs_refresh_inode: inode or fattr is NULL\n");
goto out;
}
if (inode->i_ino != fattr->fileid) {
printk("nfs_refresh_inode: inode number mismatch\n");
goto out;
}
/*
* Make sure the inode's type hasn't changed.
*/
if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
goto out_changed;
/*
* If the size or mtime changed from outside, we want
* to invalidate the local caches immediately.
*/
if (inode->i_size != fattr->size) {
#ifdef NFS_DEBUG_VERBOSE
printk("NFS: size change on %x/%ld\n", inode->i_dev, inode->i_ino);
#endif
invalid = 1;
}
if (inode->i_mtime != fattr->mtime.seconds) {
#ifdef NFS_DEBUG_VERBOSE
printk("NFS: mtime change on %x/%ld\n", inode->i_dev, inode->i_ino);
#endif
invalid = 1;
}
inode->i_mode = fattr->mode;
inode->i_nlink = fattr->nlink;
inode->i_uid = fattr->uid;
inode->i_gid = fattr->gid;
inode->i_size = fattr->size;
inode->i_blocks = fattr->blocks;
inode->i_atime = fattr->atime.seconds;
inode->i_mtime = fattr->mtime.seconds;
inode->i_ctime = fattr->ctime.seconds;
/*
* Update the read time so we don't revalidate too often.
*/
NFS_READTIME(inode) = jiffies;
error = 0;
if (invalid)
goto out_invalid;
out:
return error;
out_changed:
/*
* Big trouble! The inode has become a different object.
*/
#ifdef NFS_PARANOIA
printk("nfs_refresh_inode: mode changed, %07o to %07o\n",
inode->i_mode, fattr->mode);
#endif
fattr->mode = inode->i_mode; /* save mode */
make_bad_inode(inode);
inode->i_mode = fattr->mode; /* restore mode */
inode->i_nlink = 0;
/*
* No need to worry about unhashing the dentry, as the
* lookup validation will know that the inode is bad.
* (But we fall through to invalidate the caches.)
*/
out_invalid:
/*
* Invalidate the local caches
*/
#ifdef NFS_DEBUG_VERBOSE
printk("nfs_refresh_inode: invalidating %ld pages\n", inode->i_nrpages);
#endif
if (!S_ISDIR(inode->i_mode)) {
/* This sends off all dirty pages off to the server.
* Note that this function must not sleep. */
nfs_invalidate_pages(inode);
invalidate_inode_pages(inode);
} else
nfs_invalidate_dircache(inode);
NFS_CACHEINV(inode);
NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
goto out;
}
/*
* File system information
*/
......
......@@ -196,22 +196,44 @@ nfs_writepage_sync(struct inode *inode, struct page *page,
clear_bit(PG_uptodate, &page->flags);
goto io_error;
}
if (result != wsize)
printk("NFS: short write, wsize=%u, result=%d\n",
wsize, result);
refresh = 1;
buffer += wsize;
offset += wsize;
written += wsize;
count -= wsize;
/*
* If we've extended the file, update the inode
* now so we don't invalidate the cache.
*/
if (offset > inode->i_size)
inode->i_size = offset;
} while (count);
io_error:
/* N.B. do we want to refresh if there was an error?? (fattr valid?) */
if (refresh) {
/* See comments in nfs_wback_result */
/* N.B. I don't think this is right -- sync writes in order */
if (fattr.size < inode->i_size)
fattr.size = inode->i_size;
if (fattr.mtime.seconds < inode->i_mtime)
printk("nfs_writepage_sync: prior time??\n");
/* Solaris 2.5 server seems to send garbled
* fattrs occasionally */
if (inode->i_ino == fattr.fileid)
if (inode->i_ino == fattr.fileid) {
/*
* We expect the mtime value to change, and
* don't want to invalidate the caches.
*/
inode->i_mtime = fattr.mtime.seconds;
nfs_refresh_inode(inode, &fattr);
}
else
printk("nfs_writepage_sync: inode %ld, got %u?\n",
inode->i_ino, fattr.fileid);
}
nfs_unlock_page(page);
......@@ -327,7 +349,7 @@ create_write_request(struct inode *inode, struct page *page,
wreq = (struct nfs_wreq *) kmalloc(sizeof(*wreq), GFP_USER);
if (!wreq)
return NULL;
goto out_fail;
memset(wreq, 0, sizeof(*wreq));
task = &wreq->wb_task;
......@@ -336,11 +358,8 @@ create_write_request(struct inode *inode, struct page *page,
task->tk_action = nfs_wback_lock;
rpcauth_lookupcred(task); /* Obtain user creds */
if (task->tk_status < 0) {
rpc_release_task(task);
kfree(wreq);
return NULL;
}
if (task->tk_status < 0)
goto out_req;
/* Put the task on inode's writeback request list. */
wreq->wb_inode = inode;
......@@ -357,6 +376,12 @@ create_write_request(struct inode *inode, struct page *page,
rpc_wake_up_next(&write_queue);
return wreq;
out_req:
rpc_release_task(task);
kfree(wreq);
out_fail:
return NULL;
}
/*
......@@ -423,6 +448,8 @@ wait_on_write_request(struct nfs_wreq *req)
}
remove_wait_queue(&page->wait, &wait);
current->state = TASK_RUNNING;
if (atomic_read(&page->count) == 1)
printk("NFS: lost a page\n");
atomic_dec(&page->count);
return retval;
}
......@@ -808,15 +835,29 @@ nfs_wback_result(struct rpc_task *task)
}
clear_bit(PG_uptodate, &page->flags);
} else if (!WB_CANCELLED(req)) {
struct nfs_fattr *fattr = req->wb_fattr;
/* Update attributes as result of writeback.
* Beware: when UDP replies arrive out of order, we
* may end up overwriting a previous, bigger file size.
*/
if (req->wb_fattr->size < inode->i_size)
req->wb_fattr->size = inode->i_size;
/* possible Solaris 2.5 server bug workaround */
if (inode->i_ino == req->wb_fattr->fileid)
nfs_refresh_inode(inode, req->wb_fattr);
if (fattr->mtime.seconds >= inode->i_mtime) {
if (fattr->size < inode->i_size)
fattr->size = inode->i_size;
/* possible Solaris 2.5 server bug workaround */
if (inode->i_ino == fattr->fileid) {
/*
* We expect these values to change, and
* don't want to invalidate the caches.
*/
inode->i_size = fattr->size;
inode->i_mtime = fattr->mtime.seconds;
nfs_refresh_inode(inode, fattr);
}
else
printk("nfs_wback_result: inode %ld, got %u?\n",
inode->i_ino, fattr->fileid);
}
}
rpc_release_task(task);
......
......@@ -840,6 +840,13 @@ static int do_remount_sb(struct super_block *sb, int flags, char *data)
int retval;
struct vfsmount *vfsmnt;
/*
* Invalidate the inodes, as some mount options may be changed.
* N.B. If we are changing media, we should check the return
* from invalidate_inodes ... can't allow _any_ open files.
*/
invalidate_inodes(sb);
if (!(flags & MS_RDONLY) && sb->s_dev && is_read_only(sb->s_dev))
return -EACCES;
/*flags |= MS_RDONLY;*/
......@@ -870,8 +877,14 @@ static int do_remount(const char *dir,int flags,char *data)
struct super_block * sb = dentry->d_inode->i_sb;
retval = -EINVAL;
if (dentry == sb->s_root)
if (dentry == sb->s_root) {
/*
* Shrink the dcache and sync the device.
*/
shrink_dcache_sb(sb);
fsync_dev(sb->s_dev);
retval = do_remount_sb(sb, flags, data);
}
dput(dentry);
}
return retval;
......
......@@ -30,7 +30,7 @@ extern unsigned long occupy_region(unsigned long base, unsigned long end,
#define HAVE_AUTOIRQ
extern void *irq2dev_map[16]; /* Use only if you own the IRQ. */
extern int autoirq_setup(int waittime);
extern void autoirq_setup(int waittime);
extern int autoirq_report(int waittime);
#endif /* _LINUX_PORTIO_H */
......@@ -33,6 +33,12 @@
# define ATTRIB_NORET __attribute__((noreturn))
# define NORET_AND noreturn,
#ifdef __i386__
#define FASTCALL(x) x __attribute__((regparm(3)))
#else
#define FASTCALL(x) x
#endif
extern void math_error(void);
NORET_TYPE void panic(const char * fmt, ...)
__attribute__ ((NORET_AND format (printf, 1, 2)));
......
......@@ -241,7 +241,7 @@ extern mem_map_t * mem_map;
*/
#define __get_free_page(priority) __get_free_pages((priority),0,0)
#define __get_dma_pages(priority, order) __get_free_pages((priority),(order),1)
extern unsigned long __get_free_pages(int priority, unsigned long gfporder, int dma);
extern unsigned long FASTCALL(__get_free_pages(int priority, unsigned long gfporder, int dma));
extern inline unsigned long get_free_page(int priority)
{
......@@ -256,8 +256,8 @@ extern inline unsigned long get_free_page(int priority)
/* memory.c & swap.c*/
#define free_page(addr) free_pages((addr),0)
extern void free_pages(unsigned long addr, unsigned long order);
extern void __free_page(struct page *);
extern void FASTCALL(free_pages(unsigned long addr, unsigned long order));
extern void FASTCALL(__free_page(struct page *));
extern void show_free_areas(void);
extern unsigned long put_dirty_page(struct task_struct * tsk,unsigned long page,
......
......@@ -439,11 +439,11 @@ extern int securelevel; /* system security level */
#define CURRENT_TIME (xtime.tv_sec)
extern void sleep_on(struct wait_queue ** p);
extern void interruptible_sleep_on(struct wait_queue ** p);
extern void wake_up(struct wait_queue ** p);
extern void wake_up_interruptible(struct wait_queue ** p);
extern void wake_up_process(struct task_struct * tsk);
extern void FASTCALL(sleep_on(struct wait_queue ** p));
extern void FASTCALL(interruptible_sleep_on(struct wait_queue ** p));
extern void FASTCALL(wake_up(struct wait_queue ** p));
extern void FASTCALL(wake_up_interruptible(struct wait_queue ** p));
extern void FASTCALL(wake_up_process(struct task_struct * tsk));
extern void notify_parent(struct task_struct * tsk, int signal);
extern void force_sig(unsigned long sig,struct task_struct * p);
......
......@@ -73,7 +73,7 @@ extern unsigned int nr_swapfiles;
extern struct swap_info_struct swap_info[];
void si_swapinfo(struct sysinfo *);
unsigned long get_swap_page(void);
extern void swap_free(unsigned long);
extern void FASTCALL(swap_free(unsigned long));
/*
* vm_ops not present page codes for shared memory.
......
......@@ -104,7 +104,7 @@ struct kernel_stat kstat = { 0 };
static inline void add_to_runqueue(struct task_struct * p)
{
if (p->counter > current->counter + 3)
if (p->policy != SCHED_OTHER || p->counter > current->counter + 3)
need_resched = 1;
nr_running++;
(p->prev_run = init_task.prev_run)->next_run = p;
......@@ -649,14 +649,14 @@ int __down_interruptible(struct semaphore * sem)
}
static inline void __sleep_on(struct wait_queue **p, int state)
static void FASTCALL(__sleep_on(struct wait_queue **p, int state));
static void __sleep_on(struct wait_queue **p, int state)
{
unsigned long flags;
struct wait_queue wait = { current, NULL };
struct wait_queue wait;
if (!p)
return;
current->state = state;
wait.task = current;
write_lock_irqsave(&waitqueue_lock, flags);
__add_wait_queue(p, &wait);
write_unlock(&waitqueue_lock);
......
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