patch-2.1.87 linux/fs/umsdos/emd.c

Next file: linux/fs/umsdos/file.c
Previous file: linux/fs/umsdos/dir.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.86/linux/fs/umsdos/emd.c linux/fs/umsdos/emd.c
@@ -17,36 +17,141 @@
 
 #include <asm/uaccess.h>
 
+#include <asm/delay.h>
+
 #define PRINTK(x)
 #define Printk(x) printk x
 
 /*
-	Read a file into kernel space memory
-*/
-long umsdos_file_read_kmem (struct inode *inode,
-	struct file *filp,
-	char *buf,
-	unsigned long count)
-{
-	int ret;
-	mm_segment_t old_fs = get_fs();	
-	set_fs (KERNEL_DS);
-	ret = fat_file_read(inode,filp,buf,count);
-	set_fs (old_fs);
-	return ret;
+ * makes dentry. for name name with length len. /mn/
+ * if inode is not NULL, puts it also.
+ *
+ */
+ 
+struct dentry *creat_dentry (const char *name, const int len, const struct inode *inode)
+{
+    struct dentry *ret, *parent=NULL;	/* FIXME /mn/: whatis parent ?? */
+    struct qstr qname;
+    
+    if (inode)
+      Printk (("/mn/ creat_dentry: creating dentry with inode=%d for %20s\n", inode->i_ino, name));
+    else
+      Printk (("/mn/ creat_dentry: creating empty dentry for %20s\n", name));
+
+    qname.name = name;
+    qname.len = len;
+    qname.hash = 0;
+
+    ret = d_alloc (parent,&qname);	/* create new dentry */
+    ret->d_inode = inode;
+}
+
+
+
+/*
+ *	Read a file into kernel space memory
+ *	returns how many bytes read (from fat_file_read)
+ */
+
+ssize_t umsdos_file_read_kmem (struct inode *emd_dir,
+			    struct file *filp,
+			    char *buf,
+			    size_t count,
+			    loff_t *offs
+			    )
+{
+    int ret;
+
+    struct dentry *old_dentry;
+    mm_segment_t old_fs = get_fs();
+
+    set_fs (KERNEL_DS);
+
+    old_dentry=filp->f_dentry;	/* save it */
+    filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir);
+    *offs = filp->f_pos;
+    
+    Printk ((KERN_DEBUG "umsdos_file_read_kmem /mn/: Checkin: filp=%p, buf=%p, size=%ld, offs=%p\n", filp, buf, count, offs));
+    Printk ((KERN_DEBUG "  using emd=%d\n", emd_dir->i_ino));
+    Printk ((KERN_DEBUG "  inode=%d, i_size=%d\n", filp->f_dentry->d_inode->i_ino,filp->f_dentry->d_inode->i_size));
+    Printk ((KERN_DEBUG "  ofs=%ld\n", *offs));
+    Printk ((KERN_DEBUG "  f_pos=%ld\n", filp->f_pos));
+    Printk ((KERN_DEBUG "  name=%12s\n", filp->f_dentry->d_name.name));
+    Printk ((KERN_DEBUG "  i_binary(sb)=%d\n", MSDOS_I(filp->f_dentry->d_inode)->i_binary ));
+    Printk ((KERN_DEBUG "  f_count=%d, f_flags=%d\n", filp->f_count, filp->f_flags));
+    Printk ((KERN_DEBUG "  f_owner=%d\n", filp->f_owner));
+    Printk ((KERN_DEBUG "  f_version=%ld\n", filp->f_version));
+    Printk ((KERN_DEBUG "  f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp->f_reada, filp->f_ramax, filp->f_raend, filp->f_ralen, filp->f_rawin));
+
+    ret = fat_file_read(filp,buf,count,offs);
+    Printk ((KERN_DEBUG "fat_file_read returned with %ld!\n", ret));
+
+    filp->f_pos = *offs;	/* we needed *filp only for this? grrrr... /mn/ */
+    				/* FIXME: I have no idea what f_pos is used for. It seems to be used this way before offs was introduced.
+    				   this probably needs fixing /mn/ */
+
+    filp->f_dentry=old_dentry;			/* restore orig. dentry (it is dentry of file we need info about. Dunno why it gets passed to us
+    						   since we have no use for it, expect to store totally unrelated data of offset of EMD_FILE
+    						   end not directory in it. But what the hell now... fat_file_read requires it also, but prolly expects
+    						   it to be file* of EMD not file we want to read EMD entry about... ugh. complicated to explain :) /mn/ */
+    						   
+    						 /* FIXME: we probably need to destroy originl filp->f_dentry first ? Do we ? And how ? this way we leave all sorts of dentries, inodes etc. lying around */
+    						 /* Also FIXME: all the same problems in umsdos_file_write_kmem */
+
+    Printk ((KERN_DEBUG "  (ret) using emd=%d\n", emd_dir->i_ino));
+    Printk ((KERN_DEBUG "  (ret) inode=%d, i_size=%d\n", filp->f_dentry->d_inode->i_ino,filp->f_dentry->d_inode->i_size));
+    Printk ((KERN_DEBUG "  (ret) ofs=%ld\n", *offs));
+    Printk ((KERN_DEBUG "  (ret) f_pos=%ld\n", filp->f_pos));
+    Printk ((KERN_DEBUG "  (ret) name=%12s\n", filp->f_dentry->d_name.name));
+    Printk ((KERN_DEBUG "  (ret) i_binary(sb)=%d\n", MSDOS_I(filp->f_dentry->d_inode)->i_binary ));
+    Printk ((KERN_DEBUG "  (ret) f_count=%d, f_flags=%d\n", filp->f_count, filp->f_flags));
+    Printk ((KERN_DEBUG "  (ret) f_owner=%d\n", filp->f_owner));
+    Printk ((KERN_DEBUG "  (ret) f_version=%ld\n", filp->f_version));
+    Printk ((KERN_DEBUG "  (ret) f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp->f_reada, filp->f_ramax, filp->f_raend, filp->f_ralen, filp->f_rawin));
+
+#if 0
+    {
+      struct umsdos_dirent *mydirent=buf;
+
+      Printk ((KERN_DEBUG "  (DDD) uid=%d\n",mydirent->uid));
+      Printk ((KERN_DEBUG "  (DDD) gid=%d\n",mydirent->gid));
+      Printk ((KERN_DEBUG "  (DDD) name=>%20s<\n",mydirent->name));
+    }
+#endif  
+    
+    set_fs (old_fs);
+    return ret;
 }
+
+
 /*
 	Write to a file from kernel space
 */
-long umsdos_file_write_kmem (struct inode *inode,
-	struct file *filp,
-	const char *buf,
-	unsigned long count)
+ssize_t umsdos_file_write_kmem (struct inode *emd_dir,
+				struct file *filp,
+				const char *buf,
+				size_t  count,
+				loff_t *offs
+				)
 {
 	int ret;
 	mm_segment_t old_fs = get_fs();
+	struct dentry *old_dentry;	/* FIXME /mn/: whatis parent ?? */
+	
 	set_fs (KERNEL_DS);
-	ret = fat_file_write(inode,filp,buf,count);
+	ret = fat_file_write(filp,buf,count,offs);
+
+	old_dentry=filp->f_dentry;	/* save it */
+	filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir);
+
+	*offs = filp->f_pos;
+
+	ret = fat_file_write (filp,buf,count,offs);
+	PRINTK ((KERN_DEBUG "fat_file_write returned with %ld!\n", ret));
+
+	filp->f_pos = *offs;
+	filp->f_dentry=old_dentry;
+
 	set_fs (old_fs);
 	return ret;
 }
@@ -58,12 +163,16 @@
 
 	Return 0 if ok, a negative error code if not.
 */
-long umsdos_emd_dir_write (struct inode *emd_dir,
-	struct file *filp,
-	char *buf,	/* buffer in kernel memory, not in user space */
-	unsigned long count)
+ssize_t umsdos_emd_dir_write (struct inode *emd_dir,
+			   struct file *filp,
+			   char *buf,	/* buffer in kernel memory, not in user space */
+			   size_t  count,
+			   loff_t *offs
+			   )
 {
 	int written;
+	loff_t myofs=0;
+	
 #ifdef __BIG_ENDIAN
 	struct umsdos_dirent *d = (struct umsdos_dirent *)buf;
 #endif
@@ -78,7 +187,11 @@
 	d->rdev = cpu_to_le16 (d->rdev);
 	d->mode = cpu_to_le16 (d->mode);
 #endif	
-	written = umsdos_file_write_kmem (emd_dir,filp,buf,count);
+	
+	if (offs) myofs=*offs;	/* if offs is not NULL, read it */
+	written = umsdos_file_write_kmem (emd_dir, filp, buf, count, &myofs);
+	if (offs) *offs=myofs;	/* if offs is not NULL, store myofs there */
+	
 #ifdef __BIG_ENDIAN	
 	d->nlink = le16_to_cpu (d->nlink);
 	d->uid = le16_to_cpu (d->uid);
@@ -91,25 +204,36 @@
 #endif	
 	return written != count ? -EIO : 0;
 }
+
+
+
 /*
-	Read a block of bytes from one EMD file.
-	The block of data is NOT in user space.
-	Return 0 if ok, -EIO if any error.
-*/
-long umsdos_emd_dir_read (struct inode *emd_dir,
+ *	Read a block of bytes from one EMD file.
+ *	The block of data is NOT in user space.
+ *	Return 0 if ok, -EIO if any error.
+ */
+ 
+ssize_t umsdos_emd_dir_read (struct inode *emd_dir,
 	struct file *filp,
 	char *buf,	/* buffer in kernel memory, not in user space */
-	unsigned long count)
+	size_t count,
+	loff_t *offs
+	)
 {
+	loff_t myofs=0;
 	long int ret = 0;
 	int sizeread;
+	
+	
 #ifdef __BIG_ENDIAN
 	struct umsdos_dirent *d = (struct umsdos_dirent *)buf;
 #endif
+
+	if (offs) myofs=*offs;	/* if offs is not NULL, read it */
 	filp->f_flags = 0;
-	sizeread = umsdos_file_read_kmem (emd_dir,filp,buf,count);
+	sizeread = umsdos_file_read_kmem (emd_dir, filp, buf, count, &myofs);
 	if (sizeread != count){
-		printk ("UMSDOS: problem with EMD file. Can't read pos = %Ld (%d != %ld)\n"
+		printk ("UMSDOS: problem with EMD file. Can't read pos = %Ld (%d != %d)\n"
 			,filp->f_pos,sizeread,count);
 		ret = -EIO;
 	}
@@ -123,49 +247,105 @@
 	d->rdev = le16_to_cpu (d->rdev);
 	d->mode = le16_to_cpu (d->mode);
 #endif	
+	if (offs) *offs=myofs;	/* if offs is not NULL, store myofs there */
 	return ret;
 
 }
+
+
+
+
+/*
+	Locate the EMD file in a directory .
+
+	Return NULL if error. If ok, dir->u.umsdos_i.emd_inode 
+*/
+struct inode *umsdos_emd_dir_lookup (struct inode *dir, int creat)
+{
+    struct inode *ret = NULL;
+    int res;
+    Printk (("Entering umsdos_emd_dir_lookup\n"));
+    if (dir->u.umsdos_i.i_emd_dir != 0){
+	ret = iget (dir->i_sb,dir->u.umsdos_i.i_emd_dir);
+	Printk (("umsdos_emd_dir_lookup: deja trouve %ld %p\n"
+		 ,dir->u.umsdos_i.i_emd_dir,ret));
+    } else {
+      Printk ((KERN_DEBUG "umsdos /mn/: Looking for %20s -", UMSDOS_EMD_FILE));
+      res = compat_umsdos_real_lookup (dir, UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, &ret);
+      Printk ((KERN_DEBUG "-returned %d\n", res));
+	Printk ((KERN_DEBUG "emd_dir_lookup "));
+	if (ret != NULL){
+	    Printk ((KERN_DEBUG "Found --linux "));
+	    dir->u.umsdos_i.i_emd_dir = ret->i_ino;
+	} else if (creat) {
+                        int code;
+                        Printk ((KERN_ERR " * ERROR * /mn/: creat not yet implemented!!!!" ));
+                        Printk ((KERN_DEBUG "avant create "));
+                        atomic_inc(&dir->i_count);
+
+                        code = compat_msdos_create (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN
+                                ,S_IFREG|0777,&ret);
+                        Printk ((KERN_DEBUG "Creat EMD code %d ret %x ",code,ret));
+                        if (ret != NULL){
+                                dir->u.umsdos_i.i_emd_dir = ret->i_ino;
+                        }else{
+                                printk ("UMSDOS: Can't create EMD file\n");
+                        }
+	}
+	
+	if (ret != NULL){
+	  /* Disable UMSDOS_notify_change() for EMD file */
+	  ret->u.umsdos_i.i_emd_owner = 0xffffffff;
+	}
+
+    }
+    
+    Printk ((KERN_DEBUG "umsdos_emd_dir_lookup returning %p /mn/\n", ret));
+    if (ret != NULL) Printk ((KERN_DEBUG " debug : returning ino=%d\n",ret->i_ino));
+    return ret;
+}
+
 /*
-	Locate the EMD file in a directory and optionally, creates it.
+	creates an EMD file
 
 	Return NULL if error. If ok, dir->u.umsdos_i.emd_inode 
 */
-struct inode *umsdos_emd_dir_lookup(struct inode *dir, int creat)
+
+struct inode *umsdos_emd_dir_create(struct inode *dir, struct dentry *dentry,int mode)
 {
 	struct inode *ret = NULL;
 	if (dir->u.umsdos_i.i_emd_dir != 0){
 		ret = iget (dir->i_sb,dir->u.umsdos_i.i_emd_dir);
-		PRINTK (("deja trouve %d %x [%d] "
-			,dir->u.umsdos_i.i_emd_dir,ret,
-			 atomic_read(&ret->i_count)));
+		Printk (("deja trouve %d %x",dir->u.umsdos_i.i_emd_dir,ret));
 	}else{
-		umsdos_real_lookup (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN,&ret);
-		PRINTK (("emd_dir_lookup "));
-		if (ret != NULL){
-			PRINTK (("Find --linux "));
-			dir->u.umsdos_i.i_emd_dir = ret->i_ino;
-		}else if (creat){
-			int code;
-			PRINTK (("avant create "));
-			atomic_inc(&dir->i_count);
-			code = msdos_create (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN
-				,S_IFREG|0777,&ret);
-			PRINTK (("Creat EMD code %d ret %x ",code,ret));
-			if (ret != NULL){
-				dir->u.umsdos_i.i_emd_dir = ret->i_ino;
-			}else{
-				printk ("UMSDOS: Can't create EMD file\n");
-			}
-		}
+	    
+	    int code;
+	    Printk (("avant create "));
+	    dir->i_count++;
+	    /*			
+	       code = msdos_create (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN
+	       ,S_IFREG|0777,&ret);
+	       
+	       FIXME, I think I need a new dentry here
+	    */
+	    code = compat_msdos_create (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN, S_IFREG|0777, &ret);
+	    Printk (("Creat EMD code %d ret %x ",code,ret));
+	    if (ret != NULL){
+		dir->u.umsdos_i.i_emd_dir = ret->i_ino;
+	    }else{
+		printk ("UMSDOS: Can't create EMD file\n");
+	    }
 	}
+
 	if (ret != NULL){
-		/* Disable UMSDOS_notify_change() for EMD file */
-		ret->u.umsdos_i.i_emd_owner = 0xffffffff;
+	    /* Disable UMSDOS_notify_change() for EMD file */
+	    ret->u.umsdos_i.i_emd_owner = 0xffffffff;
 	}
 	return ret;
 }
 
+
+
 /*
 	Read an entry from the EMD file.
 	Support variable length record.
@@ -176,18 +356,28 @@
 	struct file *filp,
 	struct umsdos_dirent *entry)
 {
-	int ret = umsdos_emd_dir_read(emd_dir,filp,(char*)entry,UMSDOS_REC_SIZE);
-	if (ret == 0){
+	int ret;
+	Printk ((KERN_DEBUG "umsdos_emd_dir_readentry /mn/: entering.\n"));
+	Printk (("umsdos_emd_dir_readentry /mn/: trying to lookup %12s (ino=%d) using EMD %d\n", filp->f_dentry->d_name.name, filp->f_dentry->d_inode->i_ino, emd_dir->i_ino));
+    
+	ret = umsdos_emd_dir_read(emd_dir, filp, (char*)entry, UMSDOS_REC_SIZE, NULL);
+	if (ret == 0){ /* note /mn/: is this wrong? ret is allways 0 or -EIO. but who knows. It used to work this way... */
 		/* Variable size record. Maybe, we have to read some more */
 		int recsize = umsdos_evalrecsize (entry->name_len);
+		Printk ((KERN_DEBUG "umsdos_emd_dir_readentry /mn/: FIXME if %d > %d?\n",recsize, UMSDOS_REC_SIZE));
 		if (recsize > UMSDOS_REC_SIZE){
-			ret = umsdos_emd_dir_read(emd_dir,filp
-				,((char*)entry)+UMSDOS_REC_SIZE,recsize - UMSDOS_REC_SIZE);
+			ret = umsdos_emd_dir_read(emd_dir, filp
+				,((char*)entry)+UMSDOS_REC_SIZE,recsize - UMSDOS_REC_SIZE,NULL);
 			
 		}
 	}
+	Printk (("umsdos_emd_dir_readentry /mn/: returning %d.\n", ret));
 	return ret;
 }
+
+
+
+
 /*
 	Write an entry in the EMD file.
 	Return 0 if ok, -EIO if some error.
@@ -202,6 +392,12 @@
 	struct file filp;
 	struct umsdos_dirent *entry = &info->entry;
 	struct umsdos_dirent entry0;
+	
+	Printk (("umsdos_writeentry /mn/: entering...\n"));
+	
+	Printk ((KERN_ERR "umsdos_writeentry /mn/: FIXME! this is READ ONLY FOR NOW. RETURNING...\n"));
+	return -EIO;
+	
 	if (free_entry){
 		/* #Specification: EMD file / empty entries
 			Unused entry in the EMD file are identify
@@ -222,15 +418,20 @@
 		*/
 		memset (entry->spare,0,sizeof(entry->spare));
 	}
+
+	Printk (("umsdos_writeentry /mn/: if passed...\n"));
+
 	filp.f_pos = info->f_pos;
 	filp.f_reada = 0;
-	ret = umsdos_emd_dir_write(emd_dir,&filp,(char*)entry,info->recsize);
+	ret = umsdos_emd_dir_write(emd_dir, &filp,(char*)entry,info->recsize,NULL);
 	if (ret != 0){
 		printk ("UMSDOS: problem with EMD file. Can't write\n");
 	}else{
 		dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-		dir->i_dirt = 1;
+		/* dir->i_dirt = 1; FIXME iput/dput ??? */
 	}
+
+	Printk (("umsdos_writeentry /mn/: returning...\n"));
 	return ret;
 }
 
@@ -242,6 +443,10 @@
 	struct file filp;
 };
 
+
+
+
+
 /*
 	Fill the read buffer and take care of the byte remaining inside.
 	Unread bytes are simply move to the beginning.
@@ -256,6 +461,9 @@
 	int mustmove = buf->size - buf->pos;
 	int mustread;
 	int remain;
+	
+	Printk ((KERN_DEBUG "Entering umsdos_fillbuf, for inode %d, buf=%p\n",inode->i_ino, buf));
+	
 	if (mustmove > 0){
 		memcpy (buf->buffer,buf->buffer+buf->pos,mustmove);
 	}
@@ -264,8 +472,8 @@
 	remain = inode->i_size - buf->filp.f_pos;
 	if (remain < mustread) mustread = remain;
 	if (mustread > 0){
-		ret = umsdos_emd_dir_read (inode,&buf->filp,buf->buffer+mustmove
-			,mustread);
+		ret = umsdos_emd_dir_read (inode, &buf->filp,buf->buffer+mustmove
+			,mustread,NULL);
 		if (ret == 0) buf->size = mustmove + mustread;		
 	}else if (mustmove){
 		buf->size = mustmove;
@@ -274,6 +482,8 @@
 	return ret;
 }
 
+
+
 /*
 	General search, locate a name in the EMD file or an empty slot to
 	store it. if info->entry.name_len == 0, search the first empty
@@ -308,6 +518,7 @@
 		record, multiple contiguous record are allocated.
 	*/
 	int ret = -ENOENT;
+	/* FIXME */
 	struct inode *emd_dir = umsdos_emd_dir_lookup(dir,1);
 	if (emd_dir != NULL){
 		struct umsdos_dirent *entry = &info->entry;
@@ -320,10 +531,21 @@
 		}empty;
 		/* Read several entries at a time to speed up the search */
 		struct find_buffer buf;
-		buf.pos = 0;
-		buf.size = 0;
+		struct dentry *dentry;
+
+		memset (&buf.filp, 0, sizeof (buf.filp));
+
+		dentry = creat_dentry ("umsfind-mn", 10, emd_dir);
+	
 		buf.filp.f_pos = 0;
 		buf.filp.f_reada = 1;
+		buf.filp.f_flags = O_RDONLY;
+		buf.filp.f_dentry = dentry;
+        	buf.filp.f_op = &umsdos_file_operations;	/* /mn/ - we have to fill it with dummy values so we won't segfault */
+
+		buf.pos = 0;
+		buf.size = 0;
+
 		empty.found = 0;
 		empty.posok = emd_dir->i_size;
 		empty.onesize = 0;
@@ -388,6 +610,7 @@
 	*pt_emd_dir = emd_dir;
 	return ret;
 }
+
 /*
 	Add a new entry in the emd file
 	Return 0 if ok or a negative error code.
@@ -405,11 +628,12 @@
 		ret = -EEXIST;
 	}else if (ret == -ENOENT){
 		ret = umsdos_writeentry(dir,emd_dir,info,0);
-		PRINTK (("umsdos_newentry EDM ret = %d\n",ret));
+		Printk (("umsdos_newentry EDM ret = %d\n",ret));
 	}
 	iput (emd_dir);
 	return ret;
 }
+
 /*
 	Create a new hidden link.
 	Return 0 if ok, an error code if not.
@@ -475,15 +699,24 @@
 */
 int umsdos_isempty (struct inode *dir)
 {
+	struct dentry *dentry;
+	
 	int ret = 2;
 	struct inode *emd_dir = umsdos_emd_dir_lookup(dir,0);
 	/* If the EMD file does not exist, it is certainly empty :-) */
 	if (emd_dir != NULL){
 		struct file filp;
 		/* Find an empty slot */
+		memset (&filp, 0, sizeof (filp));
+
+		dentry = creat_dentry ("isempty-mn", 10, dir);
+	
 		filp.f_pos = 0;
 		filp.f_reada = 1;
 		filp.f_flags = O_RDONLY;
+		filp.f_dentry = dentry;
+        	filp.f_op = &umsdos_file_operations;	/* /mn/ - we have to fill it with dummy values so we won't segfault */
+        	
 		ret = 1;
 		while (filp.f_pos < emd_dir->i_size){
 			struct umsdos_dirent entry;

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