Linus, ncpfs used the same kludge as I've fixed in smbfs back in June - ncp_iget() grabs the mutex, stores the data in global variable, calls iget() with fake inumber (guaranteed cache miss) and releases mutex. read_inode() picks the data from the global variable. (a) it's an ugly kludge - after all C is not BASIC. (b) it means that iget() for NCPFS works _only_ if called by ncp_iget() (i.e. is worse than nothing) (c) it gives an artificial contention point for no good reason. Fix: instead of all this kludge-o-rama we should call get_empty_inode(), fill it with data and call insert_inode_hash(). ->read_inode is set to NULL (see (b)). Less significant cleanup: ncp_invent_ino() duplicates iunique(). Replaced and removed. Patch (against 20-pre2) follows. Please, apply it. Cheers, Al diff -urN linux-2.3.20-pre2/fs/ncpfs/dir.c linux-bird.ncpfs/fs/ncpfs/dir.c --- linux-2.3.20-pre2/fs/ncpfs/dir.c Fri Oct 8 06:00:32 1999 +++ linux-bird.ncpfs/fs/ncpfs/dir.c Sat Oct 9 11:24:57 1999 @@ -183,22 +183,6 @@ } } -/* - * Generate a unique inode number. - */ -ino_t ncp_invent_inos(unsigned long n) -{ - static ino_t ino = 2; - - if (ino + 2*n < ino) - { - /* wrap around */ - ino = 2; - } - ino += n; - return ino; -} - static inline int ncp_single_volume(struct ncp_server *server) { @@ -449,7 +433,7 @@ ino = find_inode_number(dentry, &qname); if (!ino) - ino = ncp_invent_inos(1); + ino = iunique(2); result = filldir(dirent, name, len, filp->f_pos, ino); if (!result) @@ -494,7 +478,7 @@ if (!newdent->d_inode) { entry->opened = 0; - entry->ino = ncp_invent_inos(1); + entry->ino = iunique(2); newino = ncp_iget(inode->i_sb, entry); if (newino) { newdent->d_op = &ncp_dentry_operations; @@ -517,7 +501,7 @@ ino = find_inode_number(dentry, &qname); if (!ino) - ino = ncp_invent_inos(1); + ino = iunique(2); result = filldir(dirent, entry->i.entryName, entry->i.nameLen, filp->f_pos, ino); @@ -810,7 +794,7 @@ * Create an inode for the entry. */ finfo.opened = 0; - finfo.ino = ncp_invent_inos(1); + finfo.ino = iunique(2); error = -EACCES; inode = ncp_iget(dir->i_sb, &finfo); @@ -838,7 +822,7 @@ struct inode *inode; int error = -EINVAL; - finfo->ino = ncp_invent_inos(1); + finfo->ino = iunique(2); inode = ncp_iget(dir->i_sb, finfo); if (!inode) goto out_close; diff -urN linux-2.3.20-pre2/fs/ncpfs/inode.c linux-bird.ncpfs/fs/ncpfs/inode.c --- linux-2.3.20-pre2/fs/ncpfs/inode.c Fri Oct 8 06:00:32 1999 +++ linux-bird.ncpfs/fs/ncpfs/inode.c Sat Oct 9 11:23:23 1999 @@ -31,7 +31,6 @@ #include "ncplib_kernel.h" -static void ncp_read_inode(struct inode *); static void ncp_put_inode(struct inode *); static void ncp_delete_inode(struct inode *); static void ncp_put_super(struct super_block *); @@ -39,7 +38,7 @@ static struct super_operations ncp_sops = { - ncp_read_inode, /* read inode */ + NULL, /* read inode */ NULL, /* write inode */ ncp_put_inode, /* put inode */ ncp_delete_inode, /* delete inode */ @@ -56,9 +55,6 @@ extern int ncp_symlink(struct inode*, struct dentry*, const char*); #endif -static struct ncp_entry_info *read_nwinfo = NULL; -static DECLARE_MUTEX(read_sem); - /* * Fill in the ncpfs-specific information in the inode. */ @@ -216,33 +212,7 @@ } /* - * This is called from iget() with the read semaphore held. - * The global ncp_entry_info structure has been set up by ncp_iget. - */ -static void ncp_read_inode(struct inode *inode) -{ - if (read_nwinfo == NULL) { - printk(KERN_ERR "ncp_read_inode: invalid call\n"); - return; - } - - ncp_set_attr(inode, read_nwinfo); - - if (S_ISREG(inode->i_mode)) { - inode->i_op = &ncp_file_inode_operations; - } else if (S_ISDIR(inode->i_mode)) { - inode->i_op = &ncp_dir_inode_operations; -#ifdef CONFIG_NCPFS_EXTRAS - } else if (S_ISLNK(inode->i_mode)) { - inode->i_op = &ncp_symlink_inode_operations; -#endif - } else { - inode->i_op = NULL; - } -} - -/* - * Set up the ncp_entry_info pointer and get a new inode. + * Get a new inode. */ struct inode * ncp_iget(struct super_block *sb, struct ncp_entry_info *info) @@ -254,12 +224,23 @@ return NULL; } - down(&read_sem); - read_nwinfo = info; - inode = iget(sb, info->ino); - read_nwinfo = NULL; - up(&read_sem); - if (!inode) + inode = get_empty_inode(); + if (inode) { + inode->i_sb = sb; + inode->i_dev = sb->s_dev; + inode->i_ino = info->ino; + ncp_set_attr(inode, info); + if (S_ISREG(inode->i_mode)) { + inode->i_op = &ncp_file_inode_operations; + } else if (S_ISDIR(inode->i_mode)) { + inode->i_op = &ncp_dir_inode_operations; +#ifdef CONFIG_NCPFS_EXTRAS + } else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &ncp_symlink_inode_operations; +#endif + } + insert_inode_hash(inode); + } else printk(KERN_ERR "ncp_iget: iget failed!\n"); return inode; } @@ -709,9 +690,6 @@ int init_module(void) { DPRINTK(KERN_DEBUG "ncpfs: init_module called\n"); - - init_MUTEX(&read_sem); - read_nwinfo = NULL; #ifdef DEBUG_NCP_MALLOC ncp_malloced = 0;