patch-2.0.27 linux/fs/smbfs/inode.c

Next file: linux/fs/smbfs/ioctl.c
Previous file: linux/fs/smbfs/file.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.26/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
@@ -1,7 +1,7 @@
 /*
  *  inode.c
  *
- *  Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
+ *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
  *
  */
 
@@ -29,16 +29,17 @@
 static void smb_put_super(struct super_block *);
 static void smb_statfs(struct super_block *, struct statfs *, int bufsiz);
 
-static struct super_operations smb_sops = {
-	smb_read_inode,         /* read inode */
-	smb_notify_change,      /* notify change */
+static struct super_operations smb_sops =
+{
+	smb_read_inode,		/* read inode */
+	smb_notify_change,	/* notify change */
 	NULL,			/* write inode */
 	smb_put_inode,		/* put inode */
 	smb_put_super,		/* put superblock */
 	NULL,			/* write superblock */
 	smb_statfs,		/* stat filesystem */
 	NULL
-        };
+};
 
 /* smb_read_inode: Called from iget, it only traverses the allocated
    smb_inode_info's and initializes the inode from the data found
@@ -47,187 +48,205 @@
 static void
 smb_read_inode(struct inode *inode)
 {
-        /* Our task should be extremely simple here. We only have to
-           look up the information somebody else (smb_iget) put into
-           the inode tree. The address of this information is the
-           inode->i_ino. Just to make sure everything went well, we
-           check it's there. */
-
-        struct smb_inode_info *inode_info
-                = (struct smb_inode_info *)(inode->i_ino);
-
-#if 1
-        struct smb_inode_info *root = &(SMB_SERVER(inode)->root);
-        struct smb_inode_info *check_info = root;
-
-        do {
-                if (inode_info == check_info) {
-                        if (check_info->state == SMB_INODE_LOOKED_UP) {
-                                DDPRINTK("smb_read_inode: found it!\n");
-                                goto good;
-                        }
-                        else {
-                                printk("smb_read_inode: "
-                                       "state != SMB_INODE_LOOKED_UP\n");
-                                return;
-                        }
-                }
-                check_info = check_info->next;
-        } while (check_info != root);
-
-        /* Ok, now we're in trouble. The inode info is not there. What
-           should we do now??? */
-        printk("smb_read_inode: inode info not found\n");
-        return;
-
- good:
-#endif
-        inode_info->state = SMB_INODE_VALID;
+	/* Our task should be extremely simple here. We only have to
+	   look up the information somebody else (smb_iget) put into
+	   the inode tree. */
+	struct smb_server *server = SMB_SERVER(inode);
+	struct smb_inode_info *inode_info
+	= smb_find_inode(server, inode->i_ino);
 
-        SMB_INOP(inode) = inode_info;
+	if (inode_info == NULL)
+	{
+		/* Ok, now we're in trouble. The inode info is not
+		   there. What should we do now??? */
+		printk("smb_read_inode: inode info not found\n");
+		return;
+	}
+	inode_info->state = SMB_INODE_VALID;
 
-        if (SMB_INOP(inode)->finfo.attr & aDIR)
-                inode->i_mode = SMB_SERVER(inode)->m.dir_mode;
-        else
-                inode->i_mode = SMB_SERVER(inode)->m.file_mode;
-
-        DDPRINTK("smb_read_inode: inode->i_mode = %u\n", inode->i_mode);
-
-        inode->i_nlink   = 1;
-        inode->i_uid     = SMB_SERVER(inode)->m.uid;
-        inode->i_gid     = SMB_SERVER(inode)->m.gid;
-        inode->i_size    = SMB_INOP(inode)->finfo.size;
-        inode->i_blksize = 1024;
-        inode->i_rdev    = 0;
-        if ((inode->i_blksize != 0) && (inode->i_size != 0))
-                inode->i_blocks =
-                        (inode->i_size - 1) / inode->i_blksize + 1;
-        else
-                inode->i_blocks = 0;
-
-        inode->i_mtime = SMB_INOP(inode)->finfo.mtime;
-        inode->i_ctime = SMB_INOP(inode)->finfo.ctime;
-        inode->i_atime = SMB_INOP(inode)->finfo.atime;
-
-        if (S_ISREG(inode->i_mode))
-                inode->i_op = &smb_file_inode_operations;
-        else if (S_ISDIR(inode->i_mode))
-                inode->i_op = &smb_dir_inode_operations;
-        else
-                inode->i_op = NULL;
+	SMB_INOP(inode) = inode_info;
+	inode->i_mode = inode_info->finfo.f_mode;
+	inode->i_nlink = inode_info->finfo.f_nlink;
+	inode->i_uid = inode_info->finfo.f_uid;
+	inode->i_gid = inode_info->finfo.f_gid;
+	inode->i_rdev = inode_info->finfo.f_rdev;
+	inode->i_size = inode_info->finfo.f_size;
+	inode->i_mtime = inode_info->finfo.f_mtime;
+	inode->i_ctime = inode_info->finfo.f_ctime;
+	inode->i_atime = inode_info->finfo.f_atime;
+	inode->i_blksize = inode_info->finfo.f_blksize;
+	inode->i_blocks = inode_info->finfo.f_blocks;
 
+	if (S_ISREG(inode->i_mode))
+	{
+		inode->i_op = &smb_file_inode_operations;
+	} else if (S_ISDIR(inode->i_mode))
+	{
+		inode->i_op = &smb_dir_inode_operations;
+	} else
+	{
+		inode->i_op = NULL;
+	}
 }
 
 static void
 smb_put_inode(struct inode *inode)
 {
-        struct smb_dirent *finfo  = SMB_FINFO(inode);
+	struct smb_dirent *finfo = SMB_FINFO(inode);
 	struct smb_server *server = SMB_SERVER(inode);
 	struct smb_inode_info *info = SMB_INOP(inode);
 
-	int opened        = finfo->opened;
-	int mtime         = inode->i_mtime;
-	int file_id       = finfo->fileid;
-	int isdir         = S_ISDIR(inode->i_mode);
-	unsigned long ino = inode->i_ino;
-
-	/* Remove the inode before closing the file, because the close
-           will sleep. This hopefully removes a race condition. */
-
-	clear_inode(inode);
-        smb_free_inode_info(info);
-
-        if (isdir)
+	if (S_ISDIR(inode->i_mode))
 	{
-                DDPRINTK("smb_put_inode: put directory %ld\n",
-                         inode->i_ino);
-                smb_invalid_dir_cache(ino);
-        }                
-
-        if (opened != 0)
+		smb_invalid_dir_cache(inode->i_ino);
+	}
+	if (finfo->opened != 0)
 	{
-                if (smb_proc_close(server, file_id, mtime))
+		if (smb_proc_close(server, finfo->fileid, inode->i_mtime))
 		{
-                        /* We can't do anything but complain. */
-                        DPRINTK("smb_put_inode: could not close\n");
-                }
-        }
+			/* We can't do anything but complain. */
+			DPRINTK("smb_put_inode: could not close\n");
+		}
+	}
+	smb_free_inode_info(info);
+	clear_inode(inode);
 }
 
 static void
 smb_put_super(struct super_block *sb)
 {
-        struct smb_server *server = &(SMB_SBP(sb)->s_server);
+	struct smb_server *server = &(SMB_SBP(sb)->s_server);
 
-        smb_proc_disconnect(server);
+	smb_proc_disconnect(server);
 	smb_dont_catch_keepalive(server);
 	close_fp(server->sock_file);
 
 	lock_super(sb);
 
-        smb_free_all_inodes(server);
+	smb_free_all_inodes(server);
 
-        smb_kfree_s(server->packet, server->max_xmit);
+	smb_vfree(server->packet);
+	server->packet = NULL;
 
 	sb->s_dev = 0;
-        smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info));
+	smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info));
 
 	unlock_super(sb);
 
-        MOD_DEC_USE_COUNT;
+	MOD_DEC_USE_COUNT;
 }
 
+struct smb_mount_data_v4
+{
+	int version;
+	unsigned int fd;
+	uid_t mounted_uid;
+	struct sockaddr_in addr;
+
+	char server_name[17];
+	char client_name[17];
+	char service[64];
+	char root_path[64];
+
+	char username[64];
+	char password[64];
+
+	unsigned short max_xmit;
+
+	uid_t uid;
+	gid_t gid;
+	mode_t file_mode;
+	mode_t dir_mode;
+};
+
+static int
+smb_get_mount_data(struct smb_mount_data *target, void *source)
+{
+	struct smb_mount_data_v4 *v4 = (struct smb_mount_data_v4 *) source;
+	struct smb_mount_data *cur = (struct smb_mount_data *) source;
+
+	if (source == NULL)
+	{
+		return 1;
+	}
+	if (cur->version == SMB_MOUNT_VERSION)
+	{
+		memcpy(target, cur, sizeof(struct smb_mount_data));
+		return 0;
+	}
+	if (v4->version == 4)
+	{
+		target->version = 5;
+		target->fd = v4->fd;
+		target->mounted_uid = v4->mounted_uid;
+		target->addr = v4->addr;
+
+		memcpy(target->server_name, v4->server_name, 17);
+		memcpy(target->client_name, v4->client_name, 17);
+		memcpy(target->service, v4->service, 64);
+		memcpy(target->root_path, v4->root_path, 64);
+		memcpy(target->username, v4->username, 64);
+		memcpy(target->password, v4->password, 64);
+
+		target->max_xmit = v4->max_xmit;
+		target->uid = v4->uid;
+		target->gid = v4->gid;
+		target->file_mode = v4->file_mode;
+		target->dir_mode = v4->dir_mode;
+
+		memset(target->domain, 0, 64);
+		strcpy(target->domain, "?");
+		return 0;
+	}
+	return 1;
+}
 
-/* Hmm, should we do this like the NFS mount command does? Guess so.. */
 struct super_block *
 smb_read_super(struct super_block *sb, void *raw_data, int silent)
 {
-	struct smb_mount_data *data = (struct smb_mount_data *) raw_data;
+	struct smb_mount_data data;
 	struct smb_server *server;
-        struct smb_sb_info *smb_sb;
+	struct smb_sb_info *smb_sb;
 	unsigned int fd;
 	struct file *filp;
 	kdev_t dev = sb->s_dev;
 	int error;
 
-	if (!data) {
-		printk("smb_read_super: missing data argument\n");
+	if (smb_get_mount_data(&data, raw_data) != 0)
+	{
+		printk("smb_read_super: wrong data argument\n");
 		sb->s_dev = 0;
 		return NULL;
 	}
-	fd = data->fd;
-	if (data->version != SMB_MOUNT_VERSION) {
-		printk("smb warning: mount version %s than kernel\n",
-		       (data->version < SMB_MOUNT_VERSION) ?
-                       "older" : "newer");
-	}
-	if (fd >= NR_OPEN || !(filp = current->files->fd[fd])) {
+	fd = data.fd;
+	if (fd >= NR_OPEN || !(filp = current->files->fd[fd]))
+	{
 		printk("smb_read_super: invalid file descriptor\n");
 		sb->s_dev = 0;
 		return NULL;
 	}
-	if (!S_ISSOCK(filp->f_inode->i_mode)) {
+	if (!S_ISSOCK(filp->f_inode->i_mode))
+	{
 		printk("smb_read_super: not a socket!\n");
 		sb->s_dev = 0;
 		return NULL;
 	}
+	/* We must malloc our own super-block info */
+	smb_sb = (struct smb_sb_info *) smb_kmalloc(sizeof(struct smb_sb_info),
+						    GFP_KERNEL);
 
-        /* We must malloc our own super-block info */
-        smb_sb = (struct smb_sb_info *)smb_kmalloc(sizeof(struct smb_sb_info),
-                                                   GFP_KERNEL);
-
-        if (smb_sb == NULL) {
-                printk("smb_read_super: could not alloc smb_sb_info\n");
-                return NULL;
-        }
-
-	filp->f_count += 1; 
+	if (smb_sb == NULL)
+	{
+		printk("smb_read_super: could not alloc smb_sb_info\n");
+		return NULL;
+	}
+	filp->f_count += 1;
 
 	lock_super(sb);
 
-        SMB_SBP(sb) = smb_sb;
-        
-	sb->s_blocksize = 1024; /* Eh...  Is this correct? */
+	SMB_SBP(sb) = smb_sb;
+
+	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
 	sb->s_blocksize_bits = 10;
 	sb->s_magic = SMB_SUPER_MAGIC;
 	sb->s_dev = dev;
@@ -237,100 +256,90 @@
 	server->sock_file = filp;
 	server->lock = 0;
 	server->wait = NULL;
-        server->packet = NULL;
-	server->max_xmit = data->max_xmit;
+	server->packet = NULL;
+	server->max_xmit = data.max_xmit;
 	if (server->max_xmit <= 0)
+	{
 		server->max_xmit = SMB_DEF_MAX_XMIT;
-   
+	}
 	server->tid = 0;
 	server->pid = current->pid;
 	server->mid = current->pid + 20;
 
-        server->m = *data;
+	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;
-
-        smb_init_root(server);
-
-        /*
-         * Make the connection to the server
-         */
-        
+			       (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
+	server->m.dir_mode = (server->m.dir_mode &
+			      (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;
+
+	smb_init_root(server);
+
 	error = smb_proc_connect(server);
 
 	unlock_super(sb);
 
-	if (error < 0) {
+	if (error < 0)
+	{
 		sb->s_dev = 0;
-		printk("smb_read_super: Failed connection, bailing out "
-                       "(error = %d).\n", -error);
-                goto fail;
+		DPRINTK("smb_read_super: Failed connection, bailing out "
+			"(error = %d).\n", -error);
+		goto fail;
 	}
-
-        if (server->protocol >= PROTOCOL_LANMAN2)
-                server->case_handling = CASE_DEFAULT;
-        else
-                server->case_handling = CASE_LOWER;
-
-	if ((error = smb_proc_dskattr(sb, &(SMB_SBP(sb)->s_attr))) < 0) {
-		sb->s_dev = 0;
-		printk("smb_read_super: could not get super block "
-                       "attributes\n");
-                smb_kfree_s(server->packet, server->max_xmit);
-                goto fail;
+	if (server->protocol >= PROTOCOL_LANMAN2)
+	{
+		server->case_handling = CASE_DEFAULT;
+	} else
+	{
+		server->case_handling = CASE_LOWER;
 	}
 
-	if ((error = smb_stat_root(server)) < 0) {
+	if ((error = smb_proc_dskattr(sb, &(SMB_SBP(sb)->s_attr))) < 0)
+	{
 		sb->s_dev = 0;
-		printk("smb_read_super: could not get root dir attributes\n");
-                smb_kfree_s(server->packet, server->max_xmit);
-                goto fail;
+		printk("smb_read_super: could not get super block "
+		       "attributes\n");
+		goto fail;
 	}
+	smb_init_root_dirent(server, &(server->root.finfo));
 
-	DPRINTK("smb_read_super : %u %u %u %u\n",
-                SMB_SBP(sb)->s_attr.total,
-                SMB_SBP(sb)->s_attr.blocksize,
-                SMB_SBP(sb)->s_attr.allocblocks,
-                SMB_SBP(sb)->s_attr.free);
-
-        DPRINTK("smb_read_super: SMB_SBP(sb) = %x\n", (int)SMB_SBP(sb));
-
-	if (!(sb->s_mounted = iget(sb, (int)&(server->root)))) {
+	if (!(sb->s_mounted = iget(sb, smb_info_ino(&(server->root)))))
+	{
 		sb->s_dev = 0;
 		printk("smb_read_super: get root inode failed\n");
-                smb_kfree_s(server->packet, server->max_xmit);
-                goto fail;
+		goto fail;
 	}
-
-        MOD_INC_USE_COUNT;
+	MOD_INC_USE_COUNT;
 	return sb;
 
- fail:
-	filp->f_count -= 1; 
+      fail:
+	if (server->packet != NULL)
+	{
+		smb_vfree(server->packet);
+		server->packet = NULL;
+	}
+	filp->f_count -= 1;
 	smb_dont_catch_keepalive(server);
-        smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info));
-        return NULL;
+	smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info));
+	return NULL;
 }
 
-static void 
+static void
 smb_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
 {
 	int error;
 	struct smb_dskattr attr;
 	struct statfs tmp;
-	
+
 	error = smb_proc_dskattr(sb, &attr);
 
-	if (error) {
+	if (error)
+	{
 		printk("smb_statfs: dskattr error = %d\n", -error);
 		attr.total = attr.allocblocks = attr.blocksize =
-                        attr.free = 0;
+		    attr.free = 0;
 	}
-
 	tmp.f_type = SMB_SUPER_MAGIC;
-	tmp.f_bsize = attr.blocksize*attr.allocblocks;
+	tmp.f_bsize = attr.blocksize * attr.allocblocks;
 	tmp.f_blocks = attr.total;
 	tmp.f_bfree = attr.free;
 	tmp.f_bavail = attr.free;
@@ -340,7 +349,6 @@
 	memcpy_tofs(buf, &tmp, bufsiz);
 }
 
-/* DO MORE */
 int
 smb_notify_change(struct inode *inode, struct iattr *attr)
 {
@@ -349,93 +357,101 @@
 	if ((error = inode_change_ok(inode, attr)) < 0)
 		return error;
 
-	if (((attr->ia_valid & ATTR_UID) && 
+	if (((attr->ia_valid & ATTR_UID) &&
 	     (attr->ia_uid != SMB_SERVER(inode)->m.uid)))
 		return -EPERM;
 
-	if (((attr->ia_valid & ATTR_GID) && 
+	if (((attr->ia_valid & ATTR_GID) &&
 	     (attr->ia_uid != SMB_SERVER(inode)->m.gid)))
-                return -EPERM;
+		return -EPERM;
 
 	if (((attr->ia_valid & ATTR_MODE) &&
-	     (attr->ia_mode & ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
+	(attr->ia_mode & ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
 		return -EPERM;
 
-        if ((attr->ia_valid & ATTR_SIZE) != 0) {
-
-                if ((error = smb_make_open(inode, O_WRONLY)) < 0)
-                        goto fail;
-
-                if ((error = smb_proc_trunc(SMB_SERVER(inode),
-                                            SMB_FINFO(inode)->fileid,
-                                            attr->ia_size)) < 0)
-                        goto fail;
-
-        }
-
-        if ((attr->ia_valid & (ATTR_CTIME | ATTR_MTIME | ATTR_ATIME)) != 0) {
-
-                struct smb_dirent finfo;
+	if ((attr->ia_valid & ATTR_SIZE) != 0)
+	{
 
-                finfo.attr  = 0;
+		if ((error = smb_make_open(inode, O_WRONLY)) < 0)
+			goto fail;
 
-                if ((attr->ia_valid & ATTR_CTIME) != 0)
-                        finfo.ctime = attr->ia_ctime;
-                else
-                        finfo.ctime = inode->i_ctime;
+		if ((error = smb_proc_trunc(SMB_SERVER(inode),
+					    SMB_FINFO(inode)->fileid,
+					    attr->ia_size)) < 0)
+			goto fail;
 
-                if ((attr->ia_valid & ATTR_MTIME) != 0)
-                        finfo.mtime = attr->ia_mtime;
-                else
-                        finfo.mtime = inode->i_mtime;
+	}
+	if ((attr->ia_valid & (ATTR_CTIME | ATTR_MTIME | ATTR_ATIME)) != 0)
+	{
 
-                if ((attr->ia_valid & ATTR_ATIME) != 0)
-                        finfo.atime = attr->ia_atime;
-                else
-                        finfo.atime = inode->i_atime;
+		struct smb_dirent finfo;
 
-                if ((error = smb_proc_setattr(SMB_SERVER(inode),
-                                              inode, &finfo)) >= 0) {
-                        inode->i_ctime = finfo.ctime;
-                        inode->i_mtime = finfo.mtime;
-                        inode->i_atime = finfo.atime;
-                }
-        }
+		finfo.attr = 0;
+		finfo.f_size = inode->i_size;
+		finfo.f_blksize = inode->i_blksize;
+
+		if ((attr->ia_valid & ATTR_CTIME) != 0)
+			finfo.f_ctime = attr->ia_ctime;
+		else
+			finfo.f_ctime = inode->i_ctime;
+
+		if ((attr->ia_valid & ATTR_MTIME) != 0)
+			finfo.f_mtime = attr->ia_mtime;
+		else
+			finfo.f_mtime = inode->i_mtime;
+
+		if ((attr->ia_valid & ATTR_ATIME) != 0)
+			finfo.f_atime = attr->ia_atime;
+		else
+			finfo.f_atime = inode->i_atime;
 
- fail:
-        smb_invalid_dir_cache((unsigned long)(SMB_INOP(inode)->dir));
+		if ((error = smb_proc_setattr(SMB_SERVER(inode),
+					      inode, &finfo)) >= 0)
+		{
+			inode->i_ctime = finfo.f_ctime;
+			inode->i_mtime = finfo.f_mtime;
+			inode->i_atime = finfo.f_atime;
+		}
+	}
+      fail:
+	smb_invalid_dir_cache(smb_info_ino(SMB_INOP(inode)->dir));
 
 	return error;
 }
 
-		
+
 #ifdef DEBUG_SMB_MALLOC
 int smb_malloced;
-int smb_current_malloced;
+int smb_current_kmalloced;
+int smb_current_vmalloced;
 #endif
 
-static struct file_system_type smb_fs_type = {
-        smb_read_super, "smbfs", 0, NULL
-        };
+static struct file_system_type smb_fs_type =
+{
+	smb_read_super, "smbfs", 0, NULL
+};
 
-int init_smb_fs(void)
+int
+init_smb_fs(void)
 {
-        return register_filesystem(&smb_fs_type);
+	return register_filesystem(&smb_fs_type);
 }
 
 #ifdef MODULE
-int init_module(void)
+int
+init_module(void)
 {
 	int status;
 
-        DPRINTK("smbfs: init_module called\n");
+	DPRINTK("smbfs: init_module called\n");
 
 #ifdef DEBUG_SMB_MALLOC
-        smb_malloced = 0;
-        smb_current_malloced = 0;
+	smb_malloced = 0;
+	smb_current_kmalloced = 0;
+	smb_current_vmalloced = 0;
 #endif
 
-        smb_init_dir_cache();
+	smb_init_dir_cache();
 
 	if ((status = init_smb_fs()) == 0)
 		register_symtab(0);
@@ -445,12 +461,13 @@
 void
 cleanup_module(void)
 {
-        DPRINTK("smbfs: cleanup_module called\n");
-        smb_free_dir_cache();
-        unregister_filesystem(&smb_fs_type);
+	DPRINTK("smbfs: cleanup_module called\n");
+	smb_free_dir_cache();
+	unregister_filesystem(&smb_fs_type);
 #ifdef DEBUG_SMB_MALLOC
-        printk("smb_malloced: %d\n", smb_malloced);
-        printk("smb_current_malloced: %d\n", smb_current_malloced);
+	printk("smb_malloced: %d\n", smb_malloced);
+	printk("smb_current_kmalloced: %d\n", smb_current_kmalloced);
+	printk("smb_current_vmalloced: %d\n", smb_current_vmalloced);
 #endif
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov