示例#1
0
static void
ncp_put_super(struct super_block *sb)
{
        struct ncp_server *server = NCP_SBP(sb);

	lock_super(sb);

	ncp_lock_server(server);
        ncp_disconnect(server);
	ncp_unlock_server(server);

	close_fp(server->ncp_filp);

	ncp_dont_catch_watchdog(server);
	close_fp(server->wdog_filp);
	close_fp(server->msg_filp);

        ncp_free_all_inodes(server);

        ncp_kfree_s(server->packet, server->packet_size);

	sb->s_dev = 0;
        ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
	NCP_SBP(sb) = NULL;

	unlock_super(sb);

        MOD_DEC_USE_COUNT;
}
示例#2
0
static void ncp_put_super(struct super_block *sb)
{
	struct ncp_server *server = NCP_SBP(sb);

	ncp_lock_server(server);
	ncp_disconnect(server);
	ncp_unlock_server(server);

	ncp_stop_tasks(server);

#ifdef CONFIG_NCPFS_NLS
	/* unload the NLS charsets */
	unload_nls(server->nls_vol);
	unload_nls(server->nls_io);
#endif /* CONFIG_NCPFS_NLS */

	if (server->info_filp)
		fput(server->info_filp);
	fput(server->ncp_filp);
	kill_pid(server->m.wdog_pid, SIGTERM, 1);
	put_pid(server->m.wdog_pid);

	kfree(server->priv.data);
	kfree(server->auth.object_name);
	vfree(server->rxbuf);
	vfree(server->txbuf);
	vfree(server->packet);
	sb->s_fs_info = NULL;
	kfree(server);
}
示例#3
0
文件: inode.c 项目: kprog/linux
static int  ncp_show_options(struct seq_file *seq, struct dentry *root)
{
	struct ncp_server *server = NCP_SBP(root->d_sb);
	unsigned int tmp;

	if (server->m.uid != 0)
		seq_printf(seq, ",uid=%u", server->m.uid);
	if (server->m.gid != 0)
		seq_printf(seq, ",gid=%u", server->m.gid);
	if (server->m.mounted_uid != 0)
		seq_printf(seq, ",owner=%u", server->m.mounted_uid);
	tmp = server->m.file_mode & S_IALLUGO;
	if (tmp != NCP_DEFAULT_FILE_MODE)
		seq_printf(seq, ",mode=0%o", tmp);
	tmp = server->m.dir_mode & S_IALLUGO;
	if (tmp != NCP_DEFAULT_DIR_MODE)
		seq_printf(seq, ",dirmode=0%o", tmp);
	if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
		tmp = server->m.time_out * 100 / HZ;
		seq_printf(seq, ",timeout=%u", tmp);
	}
	if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
		seq_printf(seq, ",retry=%u", server->m.retry_count);
	if (server->m.flags != 0)
		seq_printf(seq, ",flags=%lu", server->m.flags);
	if (server->m.wdog_pid != NULL)
		seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));

	return 0;
}
示例#4
0
文件: inode.c 项目: 020gzh/linux
static void ncp_put_super(struct super_block *sb)
{
	struct ncp_server *server = NCP_SBP(sb);

	ncp_lock_server(server);
	ncp_disconnect(server);
	ncp_unlock_server(server);

	ncp_stop_tasks(server);

	mutex_destroy(&server->rcv.creq_mutex);
	mutex_destroy(&server->root_setup_lock);
	mutex_destroy(&server->mutex);

	if (server->info_sock)
		sockfd_put(server->info_sock);
	sockfd_put(server->ncp_sock);
	kill_pid(server->m.wdog_pid, SIGTERM, 1);
	put_pid(server->m.wdog_pid);

	bdi_destroy(&server->bdi);
	kfree(server->priv.data);
	kfree(server->auth.object_name);
	vfree(server->rxbuf);
	vfree(server->txbuf);
	vfree(server->packet);
	call_rcu(&server->rcu, delayed_free);
}
示例#5
0
static void ncp_put_super(struct super_block *sb)
{
	struct ncp_server *server = NCP_SBP(sb);

	ncp_lock_server(server);
	ncp_disconnect(server);
	ncp_unlock_server(server);

	fput(server->ncp_filp);
	kill_proc(server->m.wdog_pid, SIGTERM, 1);

	if (server->priv.data) 
		ncp_kfree_s(server->priv.data, server->priv.len);
	if (server->auth.object_name)
		ncp_kfree_s(server->auth.object_name, server->auth.object_name_len);
	ncp_kfree_s(server->packet, server->packet_size);

	ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));

	MOD_DEC_USE_COUNT;
}
示例#6
0
static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
{
	struct dentry* d;
	struct inode* i;
	struct ncp_inode_info* ni;
	struct ncp_server* s;
	struct ncp_volume_info vi;
	struct super_block *sb = dentry->d_sb;
	int err;
	__u8 dh;
	
	d = sb->s_root;
	if (!d) {
		goto dflt;
	}
	i = d->d_inode;
	if (!i) {
		goto dflt;
	}
	ni = NCP_FINFO(i);
	if (!ni) {
		goto dflt;
	}
	s = NCP_SBP(sb);
	if (!s) {
		goto dflt;
	}
	if (!s->m.mounted_vol[0]) {
		goto dflt;
	}

	err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
	if (err) {
		goto dflt;
	}
	err = ncp_get_directory_info(s, dh, &vi);
	ncp_dirhandle_free(s, dh);
	if (err) {
		goto dflt;
	}
	buf->f_type = NCP_SUPER_MAGIC;
	buf->f_bsize = vi.sectors_per_block * 512;
	buf->f_blocks = vi.total_blocks;
	buf->f_bfree = vi.free_blocks;
	buf->f_bavail = vi.free_blocks;
	buf->f_files = vi.total_dir_entries;
	buf->f_ffree = vi.available_dir_entries;
	buf->f_namelen = 12;
	return 0;

	/* We cannot say how much disk space is left on a mounted
	   NetWare Server, because free space is distributed over
	   volumes, and the current user might have disk quotas. So
	   free space is not that simple to determine. Our decision
	   here is to err conservatively. */

dflt:;
	buf->f_type = NCP_SUPER_MAGIC;
	buf->f_bsize = NCP_BLOCK_SIZE;
	buf->f_blocks = 0;
	buf->f_bfree = 0;
	buf->f_bavail = 0;
	buf->f_namelen = 12;
	return 0;
}
示例#7
0
static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
{
	struct ncp_mount_data_kernel data;
	struct ncp_server *server;
	struct file *ncp_filp;
	struct inode *root_inode;
	struct inode *sock_inode;
	struct socket *sock;
	int error;
	int default_bufsize;
#ifdef CONFIG_NCPFS_PACKET_SIGNING
	int options;
#endif
	struct ncp_entry_info finfo;

	data.wdog_pid = NULL;
	server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
	if (!server)
		return -ENOMEM;
	sb->s_fs_info = server;

	error = -EFAULT;
	if (raw_data == NULL)
		goto out;
	switch (*(int*)raw_data) {
		case NCP_MOUNT_VERSION:
			{
				struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;

				data.flags = md->flags;
				data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
				data.mounted_uid = md->mounted_uid;
				data.wdog_pid = find_get_pid(md->wdog_pid);
				data.ncp_fd = md->ncp_fd;
				data.time_out = md->time_out;
				data.retry_count = md->retry_count;
				data.uid = md->uid;
				data.gid = md->gid;
				data.file_mode = md->file_mode;
				data.dir_mode = md->dir_mode;
				data.info_fd = -1;
				memcpy(data.mounted_vol, md->mounted_vol,
					NCP_VOLNAME_LEN+1);
			}
			break;
		case NCP_MOUNT_VERSION_V4:
			{
				struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;

				data.flags = md->flags;
				data.int_flags = 0;
				data.mounted_uid = md->mounted_uid;
				data.wdog_pid = find_get_pid(md->wdog_pid);
				data.ncp_fd = md->ncp_fd;
				data.time_out = md->time_out;
				data.retry_count = md->retry_count;
				data.uid = md->uid;
				data.gid = md->gid;
				data.file_mode = md->file_mode;
				data.dir_mode = md->dir_mode;
				data.info_fd = -1;
				data.mounted_vol[0] = 0;
			}
			break;
		default:
			error = -ECHRNG;
			if (memcmp(raw_data, "vers", 4) == 0) {
				error = ncp_parse_options(&data, raw_data);
			}
			if (error)
				goto out;
			break;
	}
	error = -EBADF;
	ncp_filp = fget(data.ncp_fd);
	if (!ncp_filp)
		goto out;
	error = -ENOTSOCK;
	sock_inode = ncp_filp->f_path.dentry->d_inode;
	if (!S_ISSOCK(sock_inode->i_mode))
		goto out_fput;
	sock = SOCKET_I(sock_inode);
	if (!sock)
		goto out_fput;
		
	if (sock->type == SOCK_STREAM)
		default_bufsize = 0xF000;
	else
		default_bufsize = 1024;

	sb->s_flags |= MS_NODIRATIME;	/* probably even noatime */
	sb->s_maxbytes = 0xFFFFFFFFU;
	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
	sb->s_blocksize_bits = 10;
	sb->s_magic = NCP_SUPER_MAGIC;
	sb->s_op = &ncp_sops;

	server = NCP_SBP(sb);
	memset(server, 0, sizeof(*server));

	server->ncp_filp = ncp_filp;
	server->ncp_sock = sock;
	
	if (data.info_fd != -1) {
		struct socket *info_sock;

		error = -EBADF;
		server->info_filp = fget(data.info_fd);
		if (!server->info_filp)
			goto out_fput;
		error = -ENOTSOCK;
		sock_inode = server->info_filp->f_path.dentry->d_inode;
		if (!S_ISSOCK(sock_inode->i_mode))
			goto out_fput2;
		info_sock = SOCKET_I(sock_inode);
		if (!info_sock)
			goto out_fput2;
		error = -EBADFD;
		if (info_sock->type != SOCK_STREAM)
			goto out_fput2;
		server->info_sock = info_sock;
	}

/*	server->lock = 0;	*/
	mutex_init(&server->mutex);
	server->packet = NULL;
/*	server->buffer_size = 0;	*/
/*	server->conn_status = 0;	*/
/*	server->root_dentry = NULL;	*/
/*	server->root_setuped = 0;	*/
#ifdef CONFIG_NCPFS_PACKET_SIGNING
/*	server->sign_wanted = 0;	*/
/*	server->sign_active = 0;	*/
#endif
	server->auth.auth_type = NCP_AUTH_NONE;
/*	server->auth.object_name_len = 0;	*/
/*	server->auth.object_name = NULL;	*/
/*	server->auth.object_type = 0;		*/
/*	server->priv.len = 0;			*/
/*	server->priv.data = NULL;		*/

	server->m = data;
	/* Althought anything producing this is buggy, it happens
	   now because of PATH_MAX changes.. */
	if (server->m.time_out < 1) {
		server->m.time_out = 10;
		printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
	}
	server->m.time_out = server->m.time_out * HZ / 100;
	server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
	server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;

#ifdef CONFIG_NCPFS_NLS
	/* load the default NLS charsets */
	server->nls_vol = load_nls_default();
	server->nls_io = load_nls_default();
#endif /* CONFIG_NCPFS_NLS */

	server->dentry_ttl = 0;	/* no caching */

	INIT_LIST_HEAD(&server->tx.requests);
	mutex_init(&server->rcv.creq_mutex);
	server->tx.creq		= NULL;
	server->rcv.creq	= NULL;
	server->data_ready	= sock->sk->sk_data_ready;
	server->write_space	= sock->sk->sk_write_space;
	server->error_report	= sock->sk->sk_error_report;
	sock->sk->sk_user_data	= server;

	init_timer(&server->timeout_tm);
#undef NCP_PACKET_SIZE
#define NCP_PACKET_SIZE 131072
	error = -ENOMEM;
	server->packet_size = NCP_PACKET_SIZE;
	server->packet = vmalloc(NCP_PACKET_SIZE);
	if (server->packet == NULL)
		goto out_nls;
	server->txbuf = vmalloc(NCP_PACKET_SIZE);
	if (server->txbuf == NULL)
		goto out_packet;
	server->rxbuf = vmalloc(NCP_PACKET_SIZE);
	if (server->rxbuf == NULL)
		goto out_txbuf;

	sock->sk->sk_data_ready	  = ncp_tcp_data_ready;
	sock->sk->sk_error_report = ncp_tcp_error_report;
	if (sock->type == SOCK_STREAM) {
		server->rcv.ptr = (unsigned char*)&server->rcv.buf;
		server->rcv.len = 10;
		server->rcv.state = 0;
		INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
		INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
		sock->sk->sk_write_space = ncp_tcp_write_space;
	} else {
		INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
		INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
		server->timeout_tm.data = (unsigned long)server;
		server->timeout_tm.function = ncpdgram_timeout_call;
	}

	ncp_lock_server(server);
	error = ncp_connect(server);
	ncp_unlock_server(server);
	if (error < 0)
		goto out_rxbuf;
	DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));

	error = -EMSGSIZE;	/* -EREMOTESIDEINCOMPATIBLE */
#ifdef CONFIG_NCPFS_PACKET_SIGNING
	if (ncp_negotiate_size_and_options(server, default_bufsize,
		NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
	{
		if (options != NCP_DEFAULT_OPTIONS)
		{
			if (ncp_negotiate_size_and_options(server, 
				default_bufsize,
				options & 2, 
				&(server->buffer_size), &options) != 0)
				
			{
				goto out_disconnect;
			}
		}
		if (options & 2)
			server->sign_wanted = 1;
	}
	else 
#endif	/* CONFIG_NCPFS_PACKET_SIGNING */
	if (ncp_negotiate_buffersize(server, default_bufsize,
  				     &(server->buffer_size)) != 0)
		goto out_disconnect;
	DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);

	memset(&finfo, 0, sizeof(finfo));
	finfo.i.attributes	= aDIR;
	finfo.i.dataStreamSize	= 0;	/* ignored */
	finfo.i.dirEntNum	= 0;
	finfo.i.DosDirNum	= 0;
#ifdef CONFIG_NCPFS_SMALLDOS
	finfo.i.NSCreator	= NW_NS_DOS;
#endif
	finfo.volume		= NCP_NUMBER_OF_VOLUMES;
	/* set dates of mountpoint to Jan 1, 1986; 00:00 */
	finfo.i.creationTime	= finfo.i.modifyTime
				= cpu_to_le16(0x0000);
	finfo.i.creationDate	= finfo.i.modifyDate
				= finfo.i.lastAccessDate
				= cpu_to_le16(0x0C21);
	finfo.i.nameLen		= 0;
	finfo.i.entryName[0]	= '\0';

	finfo.opened		= 0;
	finfo.ino		= 2;	/* tradition */

	server->name_space[finfo.volume] = NW_NS_DOS;

	error = -ENOMEM;
        root_inode = ncp_iget(sb, &finfo);
        if (!root_inode)
		goto out_disconnect;
	DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
	sb->s_root = d_alloc_root(root_inode);
        if (!sb->s_root)
		goto out_no_root;
	sb->s_root->d_op = &ncp_root_dentry_operations;
	return 0;

out_no_root:
	iput(root_inode);
out_disconnect:
	ncp_lock_server(server);
	ncp_disconnect(server);
	ncp_unlock_server(server);
out_rxbuf:
	ncp_stop_tasks(server);
	vfree(server->rxbuf);
out_txbuf:
	vfree(server->txbuf);
out_packet:
	vfree(server->packet);
out_nls:
#ifdef CONFIG_NCPFS_NLS
	unload_nls(server->nls_io);
	unload_nls(server->nls_vol);
#endif
out_fput2:
	if (server->info_filp)
		fput(server->info_filp);
out_fput:
	/* 23/12/1998 Marcin Dalecki <*****@*****.**>:
	 * 
	 * The previously used put_filp(ncp_filp); was bogous, since
	 * it doesn't proper unlocking.
	 */
	fput(ncp_filp);
out:
	put_pid(data.wdog_pid);
	sb->s_fs_info = NULL;
	kfree(server);
	return error;
}
示例#8
0
struct super_block *
ncp_read_super(struct super_block *sb, void *raw_data, int silent)
{
	struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
        struct ncp_server *server;
	struct file *ncp_filp;
	struct file *wdog_filp;
	struct file *msg_filp;
	kdev_t dev = sb->s_dev;
	int error;

	if (data == NULL)
	{
		printk("ncp_read_super: missing data argument\n");
		sb->s_dev = 0;
		return NULL;
	}

	if (data->version != NCP_MOUNT_VERSION)
	{
		printk("ncp warning: mount version %s than kernel\n",
		       (data->version < NCP_MOUNT_VERSION) ?
                       "older" : "newer");
		sb->s_dev = 0;
		return NULL;
	}

	if (   (data->ncp_fd >= NR_OPEN)
	    || ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL)
	    || (!S_ISSOCK(ncp_filp->f_inode->i_mode)))
	{
		printk("ncp_read_super: invalid ncp socket\n");
		sb->s_dev = 0;
		return NULL;
	}

	if (   (data->wdog_fd >= NR_OPEN)
	    || ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL)
	    || (!S_ISSOCK(wdog_filp->f_inode->i_mode)))
	{
		printk("ncp_read_super: invalid wdog socket\n");
		sb->s_dev = 0;
		return NULL;
	}

	if (   (data->message_fd >= NR_OPEN)
	    || ((msg_filp = current->files->fd[data->message_fd]) == NULL)
	    || (!S_ISSOCK(msg_filp->f_inode->i_mode)))
	{
		printk("ncp_read_super: invalid wdog socket\n");
		sb->s_dev = 0;
		return NULL;
	}

        /* We must malloc our own super-block info */
        server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server),
                                                   GFP_KERNEL);

        if (server == NULL)
	{
                printk("ncp_read_super: could not alloc ncp_server\n");
                return NULL;
        }

	ncp_filp->f_count += 1;
	wdog_filp->f_count += 1;
	msg_filp->f_count += 1;

	lock_super(sb);

        NCP_SBP(sb) = server;
        
	sb->s_blocksize = 1024; /* Eh...  Is this correct? */
	sb->s_blocksize_bits = 10;
	sb->s_magic = NCP_SUPER_MAGIC;
	sb->s_dev = dev;
	sb->s_op = &ncp_sops;

	server->ncp_filp    = ncp_filp;
	server->wdog_filp   = wdog_filp;
	server->msg_filp    = msg_filp;
	server->lock        = 0;
	server->wait        = NULL;
        server->packet      = NULL;
	server->buffer_size = 0;
	server->conn_status = 0;

        server->m = *data;
	server->m.file_mode = (server->m.file_mode &
			       (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
	server->m.dir_mode  = (server->m.dir_mode &
			       (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;

	/* protect against invalid mount points */
	server->m.mount_point[sizeof(server->m.mount_point)-1] = '\0';

	server->packet_size = NCP_PACKET_SIZE;
	server->packet      = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);

	if (server->packet == NULL)
	{
		printk("ncpfs: could not alloc packet\n");
		error = -ENOMEM;
		unlock_super(sb);
		goto fail;
	}
   
        /*
         * Make the connection to the server
         */

	if (ncp_catch_watchdog(server) != 0)
	{
		printk("ncp_read_super: Could not catch watchdog\n");
		error = -EINVAL;
		unlock_super(sb);
		goto fail;
	}

	if (ncp_catch_message(server) != 0)
	{
		printk("ncp_read_super: Could not catch messages\n");
		ncp_dont_catch_watchdog(server);
		error = -EINVAL;
		unlock_super(sb);
		goto fail;
	}

	ncp_lock_server(server);
	error = ncp_connect(server);
	ncp_unlock_server(server);
	unlock_super(sb);

	if (error < 0)
	{
		sb->s_dev = 0;
		printk("ncp_read_super: Failed connection, bailing out "
                       "(error = %d).\n", -error);
                ncp_kfree_s(server->packet, server->packet_size);
		ncp_dont_catch_watchdog(server);
                goto fail;
	}

        DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));

	ncp_init_root(server);

	if (!(sb->s_mounted = iget(sb, ncp_info_ino(server, &(server->root)))))
	{
		sb->s_dev = 0;
		printk("ncp_read_super: get root inode failed\n");
                goto disconnect;
	}

	if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
				     &(server->buffer_size)) != 0)
	{
		sb->s_dev = 0;
		printk("ncp_read_super: could not get bufsize\n");
		goto disconnect;
	}

	DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);

        MOD_INC_USE_COUNT;
	return sb;

 disconnect:
	ncp_lock_server(server);
	ncp_disconnect(server);
	ncp_unlock_server(server);
	ncp_kfree_s(server->packet, server->packet_size);
	ncp_dont_catch_watchdog(server);
 fail:
	ncp_filp->f_count -= 1;
	wdog_filp->f_count -= 1;
	msg_filp->f_count -= 1;
        ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
        return NULL;
}
示例#9
0
struct super_block *
ncp_read_super(struct super_block *sb, void *raw_data, int silent)
{
	struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
	struct ncp_server *server;
	struct file *ncp_filp;
	struct inode *root_inode;
	kdev_t dev = sb->s_dev;
	int error;
#ifdef CONFIG_NCPFS_PACKET_SIGNING
	int options;
#endif
	struct ncpfs_inode_info finfo;

	MOD_INC_USE_COUNT;
	if (data == NULL)
		goto out_no_data;
	if (data->version != NCP_MOUNT_VERSION)
		goto out_bad_mount;
	ncp_filp = fget(data->ncp_fd);
	if (!ncp_filp)
		goto out_bad_file;
	if (!S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode))
		goto out_bad_file2;

	lock_super(sb);

	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
	sb->s_blocksize_bits = 10;
	sb->s_magic = NCP_SUPER_MAGIC;
	sb->s_dev = dev;
	sb->s_op = &ncp_sops;

	/* We must malloc our own super-block info */
	server = (struct ncp_server *) ncp_kmalloc(sizeof(struct ncp_server),
						   GFP_KERNEL);
	if (server == NULL)
		goto out_no_server;
	NCP_SBP(sb) = server;

	server->ncp_filp = ncp_filp;
	server->lock = 0;
	server->wait = NULL;
	server->packet = NULL;
	server->buffer_size = 0;
	server->conn_status = 0;
	server->root_dentry = NULL;
	server->root_setuped = 0;
#ifdef CONFIG_NCPFS_PACKET_SIGNING
	server->sign_wanted = 0;
	server->sign_active = 0;
#endif
	server->auth.auth_type = NCP_AUTH_NONE;
	server->auth.object_name_len = 0;
	server->auth.object_name = NULL;
	server->auth.object_type = 0;
	server->priv.len = 0;
	server->priv.data = NULL;

	server->m = *data;
	/* Althought anything producing this is buggy, it happens
	   now because of PATH_MAX changes.. */
	if (server->m.time_out < 10) {
		server->m.time_out = 10;
		printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
	}
	server->m.file_mode = (server->m.file_mode &
			       (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
	server->m.dir_mode = (server->m.dir_mode &
			      (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;

	server->packet_size = NCP_PACKET_SIZE;
	server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
	if (server->packet == NULL)
		goto out_no_packet;

	ncp_lock_server(server);
	error = ncp_connect(server);
	ncp_unlock_server(server);
	if (error < 0)
		goto out_no_connect;
	DPRINTK(KERN_DEBUG "ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));

#ifdef CONFIG_NCPFS_PACKET_SIGNING
	if (ncp_negotiate_size_and_options(server, NCP_DEFAULT_BUFSIZE,
		NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
	{
		if (options != NCP_DEFAULT_OPTIONS)
		{
			if (ncp_negotiate_size_and_options(server, 
				NCP_DEFAULT_BUFSIZE,
				options & 2, 
				&(server->buffer_size), &options) != 0)
				
			{
				goto out_no_bufsize;
			}
		}
		if (options & 2)
			server->sign_wanted = 1;
	}
	else 
#endif	/* CONFIG_NCPFS_PACKET_SIGNING */
	if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
  				     &(server->buffer_size)) != 0)
		goto out_no_bufsize;
	DPRINTK(KERN_DEBUG "ncpfs: bufsize = %d\n", server->buffer_size);

	ncp_init_root(server, &finfo);
	server->name_space[finfo.nw_info.i.volNumber] = NW_NS_DOS;
        root_inode = ncp_iget(sb, &finfo);
        if (!root_inode)
		goto out_no_root;
	DPRINTK(KERN_DEBUG "ncp_read_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
        server->root_dentry = sb->s_root = d_alloc_root(root_inode, NULL);
        if (!sb->s_root)
		goto out_no_root;
	server->root_dentry->d_op = &ncp_dentry_operations;
	unlock_super(sb);
	return sb;

out_no_root:
	printk(KERN_ERR "ncp_read_super: get root inode failed\n");
	iput(root_inode);
	goto out_disconnect;
out_no_bufsize:
	printk(KERN_ERR "ncp_read_super: could not get bufsize\n");
out_disconnect:
	ncp_lock_server(server);
	ncp_disconnect(server);
	ncp_unlock_server(server);
	goto out_free_packet;
out_no_connect:
	printk(KERN_ERR "ncp_read_super: Failed connection, error=%d\n", error);
out_free_packet:
	ncp_kfree_s(server->packet, server->packet_size);
	goto out_free_server;
out_no_packet:
	printk(KERN_ERR "ncp_read_super: could not alloc packet\n");
out_free_server:
	ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
	goto out_unlock;
out_no_server:
	printk(KERN_ERR "ncp_read_super: could not alloc ncp_server\n");
out_unlock:
	/* 23/12/1998 Marcin Dalecki <*****@*****.**>:
	 * 
	 * The previously used put_filp(ncp_filp); was bogous, since
	 * it doesn't proper unlocking.
	 */
	fput(ncp_filp);
	unlock_super(sb);
	goto out;

out_bad_file2:
	fput(ncp_filp);
out_bad_file:
	printk(KERN_ERR "ncp_read_super: invalid ncp socket\n");
	goto out;
out_bad_mount:
	printk(KERN_INFO "ncp_read_super: kernel requires mount version %d\n",
		NCP_MOUNT_VERSION);
	goto out;
out_no_data:
	printk(KERN_ERR "ncp_read_super: missing data argument\n");
out:
	sb->s_dev = 0;
	MOD_DEC_USE_COUNT;
	return NULL;
}