lkml.org 
[lkml]   [1999]   [May]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
SubjectRe: ext2 warning in Linux 2.2.7
Date
From
> 
>
> I've been modifying the kernel to do inter-file prefetching (part of
> my thesis research) and have gotten similar warnings on modified
> versions of 2.2.5 and 2.2.7. In fact I'm currently trying to debug
> what's causing these warnings to occur.
>
> Nevertheless, I have not gotten them in an unmodified kernel.
>

The problem is knsfd 1.2.2a. It calls iget to find the inode and
then calls iput to release it. If the inode requested from the
client has been deleted on the server and iget happened to get
the deleted inode from the disk, iput on the deleted inode will
cause the prolem. One solutaion is to make a new function,
iget_in_use, which will only return the inode if it is in use.
I will make knsfd 1.3 soon to fix the bug.

I am enclosing the patch here. It is against Linux 2.2.7 + knfsd
1.2.2a.


--
H.J. Lu (hjl@gnu.org)
----
Index: linux/fs/inode.c
===================================================================
RCS file: /work/cvs/linux/linux/fs/inode.c,v
retrieving revision 1.5
diff -u -p -r1.5 inode.c
--- linux/fs/inode.c 1999/04/29 15:25:12 1.5
+++ linux/fs/inode.c 1999/05/03 22:09:25
@@ -809,3 +809,48 @@ void update_atime (struct inode *inode)
inode->i_atime = CURRENT_TIME;
mark_inode_dirty (inode);
} /* End Function update_atime */
+
+/* This function is called by nfsd. */
+struct inode *iget_in_use(struct super_block *sb, unsigned long ino)
+{
+ struct list_head * head = inode_hashtable + hash(sb,ino);
+ struct inode * inode;
+
+ spin_lock(&inode_lock);
+ inode = find_inode(sb, ino, head);
+ if (inode) {
+ spin_unlock(&inode_lock);
+ wait_on_inode(inode);
+ }
+ else
+ inode = get_new_inode (sb, ino, head);
+
+ /* When we get the inode, we have to check if it is in use. We
+ have to release it if it is not. */
+ if (inode) {
+ spin_lock(&inode_lock);
+ if (inode->i_nlink == 0 && inode->i_count == 1) {
+ --inode->i_count;
+ list_del(&inode->i_hash);
+ INIT_LIST_HEAD(&inode->i_hash);
+ list_del(&inode->i_list);
+ INIT_LIST_HEAD(&inode->i_list);
+ if (list_empty(&inode->i_hash)) {
+ list_del(&inode->i_list);
+ INIT_LIST_HEAD(&inode->i_list);
+ spin_unlock(&inode_lock);
+ clear_inode(inode);
+ spin_lock(&inode_lock);
+ list_add(&inode->i_list, &inode_unused);
+ inodes_stat.nr_free_inodes++;
+ }
+ else if (!(inode->i_state & I_DIRTY)) {
+ list_del(&inode->i_list);
+ list_add(&inode->i_list, &inode_in_use);
+ }
+ inode = NULL;
+ }
+ spin_unlock(&inode_lock);
+ }
+ return inode;
+}
Index: linux/fs/nfsd/nfsfh.c
===================================================================
RCS file: /work/cvs/linux/linux/fs/nfsd/nfsfh.c,v
retrieving revision 1.5
diff -u -p -r1.5 nfsfh.c
--- linux/fs/nfsd/nfsfh.c 1999/04/24 15:27:21 1.5
+++ linux/fs/nfsd/nfsfh.c 1999/05/03 20:35:45
@@ -456,7 +456,7 @@ struct dentry * lookup_inode(kdev_t dev,
}

result = ERR_PTR(-ENOENT);
- dir = iget(sb, dirino);
+ dir = iget_in_use(sb, dirino);
if (!dir)
goto out_root;
dentry = d_alloc_root(dir, NULL);
@@ -970,7 +970,7 @@ find_fh_dentry(struct knfs_fh *fh)
}

dirino = u32_to_ino_t(fh->fh_dirino);
- inode = iget(sb, fh->fh_ino);
+ inode = iget_in_use(sb, fh->fh_ino);
recheck:
if (!inode) {
dprintk(": No inode found.\n");
Index: linux/include/linux/fs.h
===================================================================
RCS file: /work/cvs/linux/linux/include/linux/fs.h,v
retrieving revision 1.4
diff -u -p -r1.4 fs.h
--- linux/include/linux/fs.h 1999/04/29 15:25:12 1.4
+++ linux/include/linux/fs.h 1999/05/03 21:36:19
@@ -818,6 +818,7 @@ extern struct dentry * __namei(const cha

extern void iput(struct inode *);
extern struct inode * iget(struct super_block *, unsigned long);
+extern struct inode * iget_in_use (struct super_block *, unsigned long);
extern void clear_inode(struct inode *);
extern struct inode * get_empty_inode(void);

Index: linux/kernel/ksyms.c
===================================================================
RCS file: /work/cvs/linux/linux/kernel/ksyms.c,v
retrieving revision 1.11
diff -u -p -r1.11 ksyms.c
--- linux/kernel/ksyms.c 1999/03/29 18:08:17 1.11
+++ linux/kernel/ksyms.c 1999/05/03 21:34:48
@@ -117,6 +117,7 @@ EXPORT_SYMBOL(get_fs_type);
EXPORT_SYMBOL(getname);
EXPORT_SYMBOL(__fput);
EXPORT_SYMBOL(iget);
+EXPORT_SYMBOL(iget_in_use);
EXPORT_SYMBOL(iput);
EXPORT_SYMBOL(__namei);
EXPORT_SYMBOL(lookup_dentry);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:51    [W:1.559 / U:0.224 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site