From: Urban Widmark <Urban.Widmark@enlight.net>

- Fix module unload (Angus Sawyer).

- Fix the smbfs error handling if kernel_thread() should fail.

- Allow high uids/gids to be used as the fake uid smbfs sets as file owner.



 fs/smbfs/Makefile         |    2 ++
 fs/smbfs/inode.c          |   42 +++++++++++++++++++++++++-----------------
 fs/smbfs/proto.h          |    5 +++--
 fs/smbfs/smbiod.c         |   22 +++++++++++++---------
 include/linux/smb_mount.h |   10 +++++-----
 5 files changed, 48 insertions(+), 33 deletions(-)

diff -puN fs/smbfs/inode.c~smbfs-fixes fs/smbfs/inode.c
--- 25/fs/smbfs/inode.c~smbfs-fixes	2003-09-13 11:32:36.000000000 -0700
+++ 25-akpm/fs/smbfs/inode.c	2003-09-13 11:32:36.000000000 -0700
@@ -25,6 +25,7 @@
 #include <linux/mount.h>
 #include <linux/net.h>
 #include <linux/vfs.h>
+#include <linux/highuid.h>
 #include <linux/smb_fs.h>
 #include <linux/smbno.h>
 #include <linux/smb_mount.h>
@@ -447,6 +448,19 @@ smb_show_options(struct seq_file *s, str
 }
 
 static void
+smb_unload_nls(struct smb_sb_info *server)
+{
+	if (server->remote_nls) {
+		unload_nls(server->remote_nls);
+		server->remote_nls = NULL;
+	}
+	if (server->local_nls) {
+		unload_nls(server->local_nls);
+		server->local_nls = NULL;
+	}
+}
+
+static void
 smb_put_super(struct super_block *sb)
 {
 	struct smb_sb_info *server = SMB_SB(sb);
@@ -461,15 +475,7 @@ smb_put_super(struct super_block *sb)
 		kill_proc(server->conn_pid, SIGTERM, 1);
 
 	smb_kfree(server->ops);
-
-	if (server->remote_nls) {
-		unload_nls(server->remote_nls);
-		server->remote_nls = NULL;
-	}
-	if (server->local_nls) {
-		unload_nls(server->local_nls);
-		server->local_nls = NULL;
-	}
+	smb_unload_nls(server);
 	sb->s_fs_info = NULL;
 	smb_unlock_server(server);
 	smb_kfree(server);
@@ -545,10 +551,8 @@ int smb_fill_super(struct super_block *s
 	if (ver == SMB_MOUNT_OLDVERSION) {
 		mnt->version = oldmnt->version;
 
-		/* FIXME: is this enough to convert uid/gid's ? */
-		mnt->mounted_uid = oldmnt->mounted_uid;
-		mnt->uid = oldmnt->uid;
-		mnt->gid = oldmnt->gid;
+		mnt->uid = low2highuid(oldmnt->uid);
+		mnt->gid = low2highuid(oldmnt->gid);
 
 		mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG;
 		mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR;
@@ -557,9 +561,8 @@ int smb_fill_super(struct super_block *s
 	} else {
 		if (parse_options(mnt, raw_data))
 			goto out_bad_option;
-
-		mnt->mounted_uid = current->uid;
 	}
+	mnt->mounted_uid = current->uid;
 	smb_setcodepage(server, &mnt->codepage);
 
 	/*
@@ -571,6 +574,11 @@ int smb_fill_super(struct super_block *s
 	else if (mnt->flags & SMB_MOUNT_DIRATTR)
 		printk("SMBFS: Using dir ff getattr\n");
 
+	if (smbiod_register_server(server) < 0) {
+		printk(KERN_ERR "smbfs: failed to start smbiod\n");
+		goto out_no_smbiod;
+	}
+
 	/*
 	 * Keep the super block locked while we get the root inode.
 	 */
@@ -584,12 +592,12 @@ int smb_fill_super(struct super_block *s
 		goto out_no_root;
 	smb_new_dentry(sb->s_root);
 
-	smbiod_register_server(server);
-
 	return 0;
 
 out_no_root:
 	iput(root_inode);
+out_no_smbiod:
+	smb_unload_nls(server);
 out_bad_option:
 	smb_kfree(mem);
 out_no_mem:
diff -puN fs/smbfs/Makefile~smbfs-fixes fs/smbfs/Makefile
--- 25/fs/smbfs/Makefile~smbfs-fixes	2003-09-13 11:32:36.000000000 -0700
+++ 25-akpm/fs/smbfs/Makefile	2003-09-13 11:32:36.000000000 -0700
@@ -32,6 +32,8 @@ proto:
 	@echo >> proto2.h " */"
 	@echo >> proto2.h ""
 	@echo >> proto2.h "struct smb_request;"
+	@echo >> proto2.h "struct sock;"
+	@echo >> proto2.h "struct statfs;"
 	@echo >> proto2.h ""
 	cproto -E "gcc -E" -e -v -I $(TOPDIR)/include -DMAKING_PROTO -D__KERNEL__ $(SRC) >> proto2.h
 	mv proto2.h proto.h
diff -puN fs/smbfs/proto.h~smbfs-fixes fs/smbfs/proto.h
--- 25/fs/smbfs/proto.h~smbfs-fixes	2003-09-13 11:32:36.000000000 -0700
+++ 25-akpm/fs/smbfs/proto.h	2003-09-13 11:32:36.000000000 -0700
@@ -1,5 +1,5 @@
 /*
- *  Autogenerated with cproto on:  Sun Sep 29 21:48:59 CEST 2002
+ *  Autogenerated with cproto on:  Sat Sep 13 17:18:51 CEST 2003
  */
 
 struct smb_request;
@@ -34,6 +34,7 @@ extern int smb_proc_read_link(struct smb
 extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const char *oldpath);
 extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry);
 extern int smb_proc_query_cifsunix(struct smb_sb_info *server);
+extern void smb_install_null_ops(struct smb_ops *ops);
 /* dir.c */
 extern struct file_operations smb_dir_operations;
 extern struct inode_operations smb_dir_inode_operations;
@@ -71,7 +72,7 @@ extern struct inode_operations smb_file_
 extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
 /* smbiod.c */
 extern void smbiod_wake_up(void);
-extern void smbiod_register_server(struct smb_sb_info *server);
+extern int smbiod_register_server(struct smb_sb_info *server);
 extern void smbiod_unregister_server(struct smb_sb_info *server);
 extern void smbiod_flush(struct smb_sb_info *server);
 extern int smbiod_retry(struct smb_sb_info *server);
diff -puN fs/smbfs/smbiod.c~smbfs-fixes fs/smbfs/smbiod.c
--- 25/fs/smbfs/smbiod.c~smbfs-fixes	2003-09-13 11:32:36.000000000 -0700
+++ 25-akpm/fs/smbfs/smbiod.c	2003-09-13 11:32:36.000000000 -0700
@@ -49,7 +49,7 @@ static spinlock_t servers_lock = SPIN_LO
 static long smbiod_flags;
 
 static int smbiod(void *);
-static void smbiod_start(void);
+static int smbiod_start(void);
 
 /*
  * called when there's work for us to do
@@ -65,30 +65,36 @@ void smbiod_wake_up()
 /*
  * start smbiod if none is running
  */
-static void smbiod_start()
+static int smbiod_start()
 {
 	pid_t pid;
 	if (smbiod_state != SMBIOD_DEAD)
-		return;
+		return 0;
 	smbiod_state = SMBIOD_STARTING;
+	__module_get(THIS_MODULE);
 	spin_unlock(&servers_lock);
 	pid = kernel_thread(smbiod, NULL, 0);
+	if (pid < 0)
+		module_put(THIS_MODULE);
 
 	spin_lock(&servers_lock);
-	smbiod_state = SMBIOD_RUNNING;
+	smbiod_state = pid < 0 ? SMBIOD_DEAD : SMBIOD_RUNNING;
 	smbiod_pid = pid;
+	return pid;
 }
 
 /*
  * register a server & start smbiod if necessary
  */
-void smbiod_register_server(struct smb_sb_info *server)
+int smbiod_register_server(struct smb_sb_info *server)
 {
+	int ret;
 	spin_lock(&servers_lock);
 	list_add(&server->entry, &smb_servers);
 	VERBOSE("%p\n", server);
-	smbiod_start();
+	ret = smbiod_start();
 	spin_unlock(&servers_lock);
+	return ret;
 }
 
 /*
@@ -282,7 +288,6 @@ out:
  */
 static int smbiod(void *unused)
 {
-	MOD_INC_USE_COUNT;
 	daemonize("smbiod");
 
 	allow_signal(SIGKILL);
@@ -330,6 +335,5 @@ static int smbiod(void *unused)
 	}
 
 	VERBOSE("SMB Kernel thread exiting (%d) ...\n", current->pid);
-	MOD_DEC_USE_COUNT;
-	return 0;
+	module_put_and_exit(0);
 }
diff -puN include/linux/smb_mount.h~smbfs-fixes include/linux/smb_mount.h
--- 25/include/linux/smb_mount.h~smbfs-fixes	2003-09-13 11:32:36.000000000 -0700
+++ 25-akpm/include/linux/smb_mount.h	2003-09-13 11:32:36.000000000 -0700
@@ -43,11 +43,11 @@ struct smb_mount_data {
 struct smb_mount_data_kernel {
 	int version;
 
-	__kernel_uid_t mounted_uid;	/* Who may umount() this filesystem? */
-	__kernel_uid_t uid;
-	__kernel_gid_t gid;
-	__kernel_mode_t file_mode;
-	__kernel_mode_t dir_mode;
+	uid_t mounted_uid;	/* Who may umount() this filesystem? */
+	uid_t uid;
+	gid_t gid;
+	mode_t file_mode;
+	mode_t dir_mode;
 
 	u32 flags;
 

_