From: Zwane Mwaikambo <zwane@linuxpower.ca>

smbfs tends to oops over a null server->ops->getattr in smb_proc_getattr().


Urban says:

 In 2.5 the server->ops is initialized when smbfs gets a connection, to
 match whatever the server is capable of or not. This happens after the
 mount syscall so smbfs is then mounted but not usable.

 Not sure if smb_lookup is always called before any other operation that
 uses server->ops. If it is then it would be enough to have a test there.

 Otherwise I will just change all users of server->ops to verify the
 pointer first and return -EIO or something.

Al Viro says (paraphrasing)

 ugh, we need mount2().

It doesn't look to me like we'll be getting mount2() in the 2.6 timeframe. 
Zwane's patch implement's Urban's workaround.



 fs/smbfs/inode.c       |    1 +
 fs/smbfs/proc.c        |   18 ++++++++++++++++++
 include/linux/smb_fs.h |    2 +-
 3 files changed, 20 insertions(+), 1 deletion(-)

diff -puN fs/smbfs/inode.c~smbfs-oops-workaround fs/smbfs/inode.c
--- 25/fs/smbfs/inode.c~smbfs-oops-workaround	2003-06-20 12:45:40.000000000 -0700
+++ 25-akpm/fs/smbfs/inode.c	2003-06-20 12:45:40.000000000 -0700
@@ -526,6 +526,7 @@ int smb_fill_super(struct super_block *s
 		goto out_no_mem;
 
 	server->ops = mem;
+	smb_install_null_ops(server->ops);
 	server->mnt = mem + sizeof(struct smb_ops);
 
 	/* Setup NLS stuff */
diff -puN fs/smbfs/proc.c~smbfs-oops-workaround fs/smbfs/proc.c
--- 25/fs/smbfs/proc.c~smbfs-oops-workaround	2003-06-20 12:45:40.000000000 -0700
+++ 25-akpm/fs/smbfs/proc.c	2003-06-20 12:45:40.000000000 -0700
@@ -2802,6 +2802,13 @@ out:
 	return result;
 }
 
+static int
+smb_proc_getattr_null(struct smb_sb_info *server, struct dentry *dir,
+		      struct smb_fattr *attr)
+{
+	return -EIO;
+}
+
 int
 smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr)
 {
@@ -3429,3 +3436,14 @@ static struct smb_ops smb_ops_unix =
 	/* .setattr	= smb_proc_setattr_unix, */
 	.truncate	= smb_proc_trunc64,
 };
+
+/* Place holder until real ops are in place */
+static struct smb_ops smb_ops_null =
+{
+	.getattr	= smb_proc_getattr_null,
+};
+
+void smb_install_null_ops(struct smb_ops *ops)
+{
+	install_ops(ops, &smb_ops_null);
+}
diff -puN include/linux/smb_fs.h~smbfs-oops-workaround include/linux/smb_fs.h
--- 25/include/linux/smb_fs.h~smbfs-oops-workaround	2003-06-20 12:45:40.000000000 -0700
+++ 25-akpm/include/linux/smb_fs.h	2003-06-20 12:45:40.000000000 -0700
@@ -198,7 +198,7 @@ smb_is_open(struct inode *i)
 	return (SMB_I(i)->open == server_from_inode(i)->generation);
 }
 
-
+extern void smb_install_null_ops(struct smb_ops *);
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_SMB_FS_H */

_