patch-2.1.63 linux/fs/ncpfs/inode.c

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

diff -u --recursive --new-file v2.1.62/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 1995, 1996 by Volker Lendecke
  *  Modified for big endian by J.F. Chadima and David S. Miller
+ *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
  *
  */
 
@@ -14,7 +15,6 @@
 #include <asm/byteorder.h>
 
 #include <linux/sched.h>
-#include <linux/ncp_fs.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/string.h>
@@ -28,84 +28,108 @@
 #ifdef CONFIG_KERNELD
 #include <linux/kerneld.h>
 #endif
+
+#include <linux/ncp_fs.h>
 #include "ncplib_kernel.h"
 
 extern int close_fp(struct file *filp);
 
-static void ncp_put_inode(struct inode *);
 static void ncp_read_inode(struct inode *);
+static void ncp_put_inode(struct inode *);
+static void ncp_delete_inode(struct inode *);
+static int  ncp_notify_change(struct inode *, struct iattr *);
 static void ncp_put_super(struct super_block *);
-static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
-static int ncp_notify_change(struct inode *inode, struct iattr *attr);
+static int  ncp_statfs(struct super_block *, struct statfs *, int);
 
 static struct super_operations ncp_sops =
 {
 	ncp_read_inode,		/* read inode */
-	ncp_notify_change,	/* notify change */
 	NULL,			/* write inode */
 	ncp_put_inode,		/* put inode */
+	ncp_delete_inode,       /* delete inode */
+	ncp_notify_change,	/* notify change */
 	ncp_put_super,		/* put superblock */
 	NULL,			/* write superblock */
 	ncp_statfs,		/* stat filesystem */
-	NULL
+	NULL                    /* remount */
 };
 
-/* ncp_read_inode: Called from iget, it only traverses the allocated
-   ncp_inode_info's and initializes the inode from the data found
-   there.  It does not allocate or deallocate anything. */
+static struct nw_file_info *read_nwinfo = NULL;
+static struct semaphore read_sem = MUTEX;
 
-static void ncp_read_inode(struct inode *inode)
+/*
+ * Fill in the ncpfs-specific information in the inode.
+ */
+void ncp_update_inode(struct inode *inode, struct nw_file_info *nwinfo)
 {
-	/* Our task should be extremely simple here. We only have to
-	   look up the information somebody else (ncp_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 ncp_inode_info *inode_info = ncp_find_inode(inode);
-
-	if (inode_info == NULL) {
-		/* Ok, now we're in trouble. The inode info is not there. What
-		   should we do now??? */
-		printk("ncp_read_inode: inode info not found\n");
-		return;
-	}
-	inode_info->state = NCP_INODE_VALID;
+	NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
+	NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
+	NCP_FINFO(inode)->volNumber = nwinfo->i.volNumber;
+
+	NCP_FINFO(inode)->opened = nwinfo->opened;
+	NCP_FINFO(inode)->access = nwinfo->access;
+	NCP_FINFO(inode)->server_file_handle = nwinfo->server_file_handle;
+	memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
+			sizeof(nwinfo->file_handle));
+#ifdef NCPFS_DEBUG_VERBOSE
+printk(KERN_DEBUG "ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
+nwinfo->i.entryName, NCP_FINFO(inode)->volNumber, NCP_FINFO(inode)->dirEntNum);
+#endif
+}
 
-	NCP_INOP(inode) = inode_info;
-	inode_info->inode = inode;
+/*
+ * Fill in the inode based on the nw_file_info structure.
+ */
+static void ncp_set_attr(struct inode *inode, struct nw_file_info *nwinfo)
+{
+	struct nw_info_struct *nwi = &nwinfo->i;
+	struct ncp_server *server = NCP_SERVER(inode);
 
-	if (NCP_ISTRUCT(inode)->attributes & aDIR) {
-		inode->i_mode = NCP_SERVER(inode)->m.dir_mode;
+	if (nwi->attributes & aDIR) {
+		inode->i_mode = server->m.dir_mode;
 		/* for directories dataStreamSize seems to be some
 		   Object ID ??? */
 		inode->i_size = 512;
 	} else {
-		inode->i_mode = NCP_SERVER(inode)->m.file_mode;
-		inode->i_size = le32_to_cpu(NCP_ISTRUCT(inode)->dataStreamSize);
+		inode->i_mode = server->m.file_mode;
+		inode->i_size = le32_to_cpu(nwi->dataStreamSize);
 	}
 
-	DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
+	DDPRINTK(KERN_DEBUG "ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
 
 	inode->i_nlink = 1;
-	inode->i_uid = NCP_SERVER(inode)->m.uid;
-	inode->i_gid = NCP_SERVER(inode)->m.gid;
+	inode->i_uid = server->m.uid;
+	inode->i_gid = server->m.gid;
 	inode->i_blksize = 512;
 	inode->i_rdev = 0;
 
+	inode->i_blocks = 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 = ncp_date_dos2unix(le16_to_cpu(NCP_ISTRUCT(inode)->modifyTime),
-			    le16_to_cpu(NCP_ISTRUCT(inode)->modifyDate));
-	inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(NCP_ISTRUCT(inode)->creationTime),
-			  le16_to_cpu(NCP_ISTRUCT(inode)->creationDate));
+	inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime),
+			  		   le16_to_cpu(nwi->modifyDate));
+	inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime),
+			    		   le16_to_cpu(nwi->creationDate));
 	inode->i_atime = ncp_date_dos2unix(0,
-			le16_to_cpu(NCP_ISTRUCT(inode)->lastAccessDate));
+					   le16_to_cpu(nwi->lastAccessDate));
+	ncp_update_inode(inode, nwinfo);
+}
+
+/*
+ * This is called from iget() with the read semaphore held. 
+ * The global ncpfs_file_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;
@@ -116,73 +140,103 @@
 	}
 }
 
-static void ncp_put_inode(struct inode *inode)
+/*
+ * Set up the ncpfs_inode_info pointer and get a new inode.
+ */
+struct inode * 
+ncp_iget(struct super_block *sb, struct ncpfs_inode_info *info)
 {
-	struct nw_file_info *finfo = NCP_FINFO(inode);
-	struct super_block *sb = inode->i_sb;
+	struct inode *inode;
 
-	lock_super(sb);
-	if (finfo->opened != 0) {
-		if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle) != 0) {
-			/* We can't do anything but complain. */
-			printk("ncp_put_inode: could not close\n");
-		}
+	if (info == NULL) {
+		printk(KERN_ERR "ncp_iget: info is NULL\n");
+		return NULL;
 	}
-	DDPRINTK("ncp_put_inode: put %s\n",
-		 finfo->i.entryName);
 
-	ncp_free_inode_info(NCP_INOP(inode));
+	down(&read_sem);
+	read_nwinfo = &info->nw_info;
+	inode = iget(sb, info->ino);
+	read_nwinfo = NULL;
+	up(&read_sem);
+	if (!inode)
+		printk(KERN_ERR "ncp_iget: iget failed!\n");
+	return inode;
+}
+
+static void ncp_put_inode(struct inode *inode)
+{
+	if (inode->i_count == 1)
+		inode->i_nlink = 0;
+}
 
+static void
+ncp_delete_inode(struct inode *inode)
+{
 	if (S_ISDIR(inode->i_mode)) {
-		DDPRINTK("ncp_put_inode: put directory %ld\n",
-			 inode->i_ino);
+		DDPRINTK(KERN_DEBUG "ncp_delete_inode: put directory %ld\n", inode->i_ino);
 		ncp_invalid_dir_cache(inode);
 	}
+
+	if (NCP_FINFO(inode)->opened && ncp_make_closed(inode) != 0) {
+		/* We can't do anything but complain. */
+		printk(KERN_ERR "ncp_delete_inode: could not close\n");
+	}
 	clear_inode(inode);
-	unlock_super(sb);
+}
+
+static void ncp_init_root(struct ncp_server *server,
+			struct ncpfs_inode_info *info)
+{
+	struct ncp_inode_info *root = &(server->root);
+	struct nw_info_struct *i = &(root->finfo.i);
+	unsigned short dummy;
+
+	DPRINTK(KERN_DEBUG "ncp_init_root: i = %x\n", (int) i);
+
+	i->attributes	 = aDIR;
+	i->dataStreamSize= 1024;
+	i->dirEntNum	 = 0;
+	i->DosDirNum	 = 0;
+	i->volNumber	 = NCP_NUMBER_OF_VOLUMES + 1;	/* illegal volnum */
+	ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
+	ncp_date_unix2dos(0, &(i->modifyTime  ), &(i->modifyDate));
+	ncp_date_unix2dos(0, &(dummy          ), &(i->lastAccessDate));
+	i->creationTime	 = le16_to_cpu(i->creationTime);
+	i->creationDate	 = le16_to_cpu(i->creationDate);
+	i->modifyTime	 = le16_to_cpu(i->modifyTime);
+	i->modifyDate	 = le16_to_cpu(i->modifyDate);
+	i->lastAccessDate= le16_to_cpu(i->lastAccessDate);
+	i->nameLen	 = 0;
+	i->entryName[0]  = '\0';
+
+	root->finfo.opened= 0;
+	info->ino = 1;
+	info->nw_info = root->finfo;
 }
 
 struct super_block *
- ncp_read_super(struct super_block *sb, void *raw_data, int silent)
+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;
+	struct ncpfs_inode_info finfo;
 
-	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_dentry->d_inode->i_mode))) {
-		printk("ncp_read_super: invalid ncp 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++;
+	MOD_INC_USE_COUNT;
+	if (data == NULL)
+		goto out_no_data;
+	if (data->version != NCP_MOUNT_VERSION)
+		goto out_bad_mount;
+	if ((data->ncp_fd >= NR_OPEN) ||
+	    ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL) ||
+	    !S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode))
+		goto out_bad_file;
 
 	lock_super(sb);
-
-	NCP_SBP(sb) = server;
+	ncp_filp->f_count++;
 
 	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
 	sb->s_blocksize_bits = 10;
@@ -190,6 +244,13 @@
 	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;
@@ -202,7 +263,7 @@
 	   now because of PATH_MAX changes.. */
 	if (server->m.time_out < 10) {
 		server->m.time_out = 10;
-		printk("You need to recompile your ncpfs utils..\n");
+		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;
@@ -211,54 +272,74 @@
 
 	server->packet_size = NCP_PACKET_SIZE;
 	server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
+	if (server->packet == NULL)
+		goto out_no_packet;
 
-	if (server->packet == NULL) {
-		printk("ncpfs: could not alloc packet\n");
-		error = -ENOMEM;
-		unlock_super(sb);
-		goto fail;
-	}
 	ncp_lock_server(server);
 	error = ncp_connect(server);
 	ncp_unlock_server(server);
-	unlock_super(sb);
+	if (error < 0)
+		goto out_no_connect;
+	DPRINTK(KERN_DEBUG "ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
+
+	error = ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
+				    		&(server->buffer_size));
+	if (error)
+		goto out_no_bufsize;
+	DPRINTK(KERN_DEBUG "ncpfs: bufsize = %d\n", server->buffer_size);
+
+	ncp_init_root(server, &finfo);
+        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);
+        sb->s_root = d_alloc_root(root_inode, NULL);
+        if (!sb->s_root)
+		goto out_no_root;
 
-	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);
-		goto fail;
-	}
-	DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
-
-	ncp_init_root(server);
-
-        if (!(sb->s_root = d_alloc_root(iget(sb,ncp_info_ino(server,
-						    &(server->root))),NULL))) {
-		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;
+	unlock_super(sb);
 	return sb;
 
-      disconnect:
+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);
-      fail:
-	put_filp(ncp_filp);
+	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:
+	put_filp(ncp_filp);
+	unlock_super(sb);
+	goto out;
+
+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;
 }
 
@@ -275,20 +356,17 @@
 	close_fp(server->ncp_filp);
 	kill_proc(server->m.wdog_pid, SIGTERM, 0);
 
-	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;
 
+	sb->s_dev = 0;
 	unlock_super(sb);
 
 	MOD_DEC_USE_COUNT;
 }
 
-static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
 {
 	struct statfs tmp;
 
@@ -306,7 +384,7 @@
 	tmp.f_files = -1;
 	tmp.f_ffree = -1;
 	tmp.f_namelen = 12;
-	copy_to_user(buf, &tmp, bufsiz);
+	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
 }
 
 static int ncp_notify_change(struct inode *inode, struct iattr *attr)
@@ -359,11 +437,9 @@
 		info.lastAccessDate = le16_to_cpu(info.lastAccessDate);
 	}
 	if (info_mask != 0) {
-		if ((result =
-		     ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
-						      NCP_ISTRUCT(inode),
-							info_mask,
-							&info)) != 0) {
+		result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
+				      inode, info_mask, &info);
+		if (result != 0) {
 			result = -EACCES;
 
 			if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
@@ -379,8 +455,7 @@
 	if ((attr->ia_valid & ATTR_SIZE) != 0) {
 		int written;
 
-		DPRINTK("ncpfs: trying to change size of %s to %ld\n",
-			NCP_ISTRUCT(inode)->entryName, attr->ia_size);
+		DPRINTK(KERN_DEBUG "ncpfs: trying to change size to %ld\n", attr->ia_size);
 
 		if ((result = ncp_make_open(inode, O_RDWR)) < 0) {
 			return -EACCES;
@@ -390,13 +465,12 @@
 
 		/* According to ndir, the changes only take effect after
 		   closing the file */
-		ncp_close_file(NCP_SERVER(inode),
-			       NCP_FINFO(inode)->file_handle);
-		NCP_FINFO(inode)->opened = 0;
-
-		result = 0;
+		result = ncp_make_closed(inode);
 	}
-	ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
+	/*
+	 * We need a dentry here ...
+	 */
+	/* ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode); */
 
 	return result;
 }
@@ -423,7 +497,10 @@
 
 int init_module(void)
 {
-	DPRINTK("ncpfs: init_module called\n");
+	DPRINTK(KERN_DEBUG "ncpfs: init_module called\n");
+
+	read_sem = MUTEX;
+	read_nwinfo = NULL;
 
 #ifdef DEBUG_NCP_MALLOC
 	ncp_malloced = 0;
@@ -436,12 +513,12 @@
 
 void cleanup_module(void)
 {
-	DPRINTK("ncpfs: cleanup_module called\n");
+	DPRINTK(KERN_DEBUG "ncpfs: cleanup_module called\n");
 	ncp_free_dir_cache();
 	unregister_filesystem(&ncp_fs_type);
 #ifdef DEBUG_NCP_MALLOC
-	printk("ncp_malloced: %d\n", ncp_malloced);
-	printk("ncp_current_malloced: %d\n", ncp_current_malloced);
+	printk(KERN_DEBUG "ncp_malloced: %d\n", ncp_malloced);
+	printk(KERN_DEBUG "ncp_current_malloced: %d\n", ncp_current_malloced);
 #endif
 }
 

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