Commit 4bbfc32d authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.80pre4

parent 472bbf0a
......@@ -285,6 +285,7 @@ CONFIG_82C710_MOUSE=y
#
# Kernel hacking
#
# CONFIG_PROFILE is not set
CONFIG_PROFILE=y
CONFIG_PROFILE_SHIFT=2
# CONFIG_MAGIC_SYSRQ is not set
CONFIG_VGA_CONSOLE=y
......@@ -47,7 +47,7 @@ else
endif
ifeq ($(CONFIG_ISDN_DRV_ICN),y)
L_OBJS += icn/icn.o
L_OBJS += icn/icn_obj.o
SUB_DIRS += icn
MOD_SUB_DIRS += icn
else
......
L_OBJS :=
M_OBJS :=
ifeq ($(CONFIG_ISDN_DRV_ICN),y)
L_OBJS += icn.o
O_TARGET := icn_obj.o
O_OBJS := icn.o
else
M_OBJS += icn.o
M_OBJS := icn.o
endif
include $(TOPDIR)/Rules.make
......@@ -648,7 +648,17 @@ struct inode *iget(struct super_block *sb, unsigned long ino)
void insert_inode_hash(struct inode *inode)
{
struct list_head *head = inode_hashtable + hash(inode->i_sb, inode->i_ino);
spin_lock(&inode_lock);
list_add(&inode->i_hash, head);
spin_unlock(&inode_lock);
}
void remove_inode_hash(struct inode *inode)
{
spin_lock(&inode_lock);
list_del(&inode->i_hash);
INIT_LIST_HEAD(&inode->i_hash);
spin_unlock(&inode_lock);
}
void iput(struct inode *inode)
......@@ -689,6 +699,9 @@ void iput(struct inode *inode)
list_add(&inode->i_list, inode_in_use.prev);
}
#ifdef INODE_PARANOIA
if (!list_empty(&inode->i_dentry))
printk("iput: device %s inode %ld still has aliases!\n",
kdevname(inode->i_dev), inode->i_ino);
if (inode->i_count)
printk("iput: device %s inode %ld count changed, count=%d\n",
kdevname(inode->i_dev), inode->i_ino, inode->i_count);
......
......@@ -355,17 +355,50 @@ nfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
/*
* Free all unused dentries in an inode's alias list.
*
* Subtle note: we have to be very careful not to cause
* any IO operations with the stale dentries, as this
* could cause file corruption. But since the dentry
* count is 0 and all pending IO for a dentry has been
* flushed when the count went to 0, we're safe here.
*/
void nfs_free_dentries(struct inode *inode)
{
struct list_head *tmp, *head = &inode->i_dentry;
restart:
tmp = head;
while ((tmp = tmp->next) != head) {
struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
if (!dentry->d_count) {
printk("nfs_free_dentries: freeing %s/%s, i_count=%d\n",
dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_count);
dget(dentry);
d_drop(dentry);
dput(dentry);
goto restart;
}
}
}
/*
* This is our own version of iget that looks up inodes by file handle
* instead of inode number. We use this technique instead of using
* the vfs read_inode function because there is no way to pass the
* file handle or current attributes into the read_inode function.
*
* Note carefully the special handling of busy inodes (i_count > 1).
* With the Linux 2.1.xx dcache all inodes except hard links must
* have i_count == 1 after iget(). Otherwise, it indicates that the
* server has reused a fileid (i_ino) and we have a stale inode.
*/
struct inode *
nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
int error;
int error, max_count;
struct inode *inode = NULL;
struct nfs_fattr newfattr;
......@@ -377,6 +410,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle,
if (error)
goto out_bad_attr;
}
retry:
inode = iget(sb, fattr->fileid);
if (!inode)
goto out_no_inode;
......@@ -388,6 +423,40 @@ printk("nfs_fhget: impossible\n");
if (inode->i_ino != fattr->fileid)
goto out_bad_id;
/*
* Check for busy inodes, and attempt to get rid of any
* unused local references. If successful, we release the
* inode and try again.
*
* Note that the busy test uses the values in the fattr,
* as the inode may have become a different object.
* (We can probably handle modes changes here, too.)
*/
max_count = S_ISDIR(fattr->mode) ? 1 : fattr->nlink;
if (inode->i_count > max_count) {
printk("nfs_fhget: inode %ld busy, i_count=%d, i_nlink=%d\n",
inode->i_ino, inode->i_count, inode->i_nlink);
nfs_free_dentries(inode);
if (inode->i_count > max_count) {
printk("nfs_fhget: inode %ld still busy, i_count=%d\n",
inode->i_ino, inode->i_count);
if (!list_empty(&inode->i_dentry)) {
struct dentry *dentry;
dentry = list_entry(inode->i_dentry.next,
struct dentry, d_alias);
printk("nfs_fhget: killing %s/%s filehandle\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
memset(dentry->d_fsdata, 0, sizeof(*fhandle));
} else
printk("NFS: inode %ld busy, no aliases?\n",
inode->i_ino);
make_bad_inode(inode);
remove_inode_hash(inode);
}
iput(inode);
goto retry;
}
/*
* Check whether the mode has been set, as we only want to
* do this once. (We don't allow inodes to change types.)
......
......@@ -775,6 +775,7 @@ extern void clear_inode(struct inode *);
extern struct inode * get_empty_inode(void);
extern void insert_inode_hash(struct inode *);
extern void remove_inode_hash(struct inode *);
extern int get_unused_fd(void);
extern void put_unused_fd(int);
extern struct file * get_empty_filp(void);
......
......@@ -382,6 +382,7 @@ EXPORT_SYMBOL(read_ahead);
EXPORT_SYMBOL(get_hash_table);
EXPORT_SYMBOL(get_empty_inode);
EXPORT_SYMBOL(insert_inode_hash);
EXPORT_SYMBOL(remove_inode_hash);
EXPORT_SYMBOL(make_bad_inode);
EXPORT_SYMBOL(is_bad_inode);
EXPORT_SYMBOL(event);
......
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