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;

Reply via email to