patch-2.1.120 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.119/linux/fs/umsdos/emd.c linux/fs/umsdos/emd.c
@@ -20,35 +20,24 @@
 
 #include <asm/delay.h>
 
-#define PRINTK(x)
-#define Printk(x) printk x
 
 /*
  *    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,
+ssize_t umsdos_file_read_kmem (	struct file *filp,
 				char *buf,
-				size_t count,
-				loff_t *offs)
+				size_t count)
 {
 	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, NULL);
-	*offs = filp->f_pos;
-
-	PRINTK ((KERN_DEBUG "umsdos_file_read_kmem /mn/: Checkin: filp=%p, buf=%p, size=%d, offs=%p\n", filp, buf, count, offs));
-	PRINTK ((KERN_DEBUG "  using emd=%ld\n", emd_dir->i_ino));
+	PRINTK ((KERN_DEBUG "umsdos_file_read_kmem /mn/: Checkin: filp=%p, buf=%p, size=%d\n", filp, buf, count));
 	PRINTK ((KERN_DEBUG "  inode=%lu, i_size=%lu\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_size));
-	PRINTK ((KERN_DEBUG "  ofs=%ld\n", (unsigned long) *offs));
 	PRINTK ((KERN_DEBUG "  f_pos=%Lu\n", filp->f_pos));
 	PRINTK ((KERN_DEBUG "  name=%.*s\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name));
 	PRINTK ((KERN_DEBUG "  i_binary(sb)=%d\n", MSDOS_I (filp->f_dentry->d_inode)->i_binary));
@@ -58,25 +47,11 @@
 	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));
 
 	MSDOS_I (filp->f_dentry->d_inode)->i_binary = 2;
-	ret = fat_file_read (filp, buf, count, offs);
-	PRINTK ((KERN_DEBUG "fat_file_read returned with %d!\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/ */
-
-	d_drop (filp->f_dentry);	/* FIXME: hmmmm... we should not dispose of it in this way ? */
-	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 original 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 */
+	ret = fat_file_read (filp, buf, count, &filp->f_pos);
+	PRINTK ((KERN_DEBUG "fat_file_read returned with %d!\n", ret));
 
-	PRINTK ((KERN_DEBUG "  (ret) using emd=%lu\n", emd_dir->i_ino));
 	PRINTK ((KERN_DEBUG "  (ret) inode=%lu, i_size=%lu\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_size));
-	PRINTK ((KERN_DEBUG "  (ret) ofs=%Lu\n", *offs));
 	PRINTK ((KERN_DEBUG "  (ret) f_pos=%Lu\n", filp->f_pos));
 	PRINTK ((KERN_DEBUG "  (ret) name=%.*s\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name));
 	PRINTK ((KERN_DEBUG "  (ret) i_binary(sb)=%d\n", MSDOS_I (filp->f_dentry->d_inode)->i_binary));
@@ -89,9 +64,9 @@
 	{
 		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));
+		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
 
@@ -102,25 +77,23 @@
 
 /*
  *    Write to file from kernel space. 
- *      Does the real job, assumes all structures are initialized !
+ *      Does the real job, assumes all structures are initialized!
  */
 
 
 ssize_t umsdos_file_write_kmem_real (struct file * filp,
 				     const char *buf,
-				     size_t count,
-				     loff_t * offs)
+				     size_t count)
 {
 	ssize_t ret;
 	mm_segment_t old_fs = get_fs ();
 
 	set_fs (KERNEL_DS);
 
-	PRINTK ((KERN_DEBUG "umsdos_file_write_kmem /mn/: Checkin: filp=%p, buf=%p, size=%d, offs=%p\n", filp, buf, count, offs));
+	PRINTK ((KERN_DEBUG "umsdos_file_write_kmem /mn/: Checkin: filp=%p, buf=%p, size=%d\n", filp, buf, count));
 	PRINTK ((KERN_DEBUG "  struct dentry=%p\n", filp->f_dentry));
 	PRINTK ((KERN_DEBUG "  struct inode=%p\n", filp->f_dentry->d_inode));
 	PRINTK ((KERN_DEBUG "  inode=%lu, i_size=%lu\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_size));
-	PRINTK ((KERN_DEBUG "  ofs=%ld\n", (unsigned long) *offs));
 	PRINTK ((KERN_DEBUG "  f_pos=%Lu\n", filp->f_pos));
 	PRINTK ((KERN_DEBUG "  name=%.*s\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name));
 	PRINTK ((KERN_DEBUG "  i_binary(sb)=%d\n", MSDOS_I (filp->f_dentry->d_inode)->i_binary));
@@ -131,13 +104,13 @@
 
 	/* note: i_binary=2 is for CVF-FAT. We put it here, instead of
 	 * umsdos_file_write_kmem, since it is also wise not to compress symlinks
-	 * (in unlikely event that they are > 512 bytes and can be compressed 
-	 * FIXME: should we set it when reading symlink too ? */
+	 * (in the unlikely event that they are > 512 bytes and can be compressed 
+	 * FIXME: should we set it when reading symlinks too? */
 
 	MSDOS_I (filp->f_dentry->d_inode)->i_binary = 2;
 
-	ret = fat_file_write (filp, buf, count, offs);
-	PRINTK ((KERN_DEBUG "fat_file_write returned with %ld!\n", ret));
+	ret = fat_file_write (filp, buf, count, &filp->f_pos);
+	Printk ((KERN_DEBUG "fat_file_write returned with %ld!\n", (long int) ret));
 
 	set_fs (old_fs);
 	return ret;
@@ -145,32 +118,22 @@
 
 
 /*
- *    Write to a file from kernel space
+ *    Write to a file from kernel space.
  */
 
-ssize_t umsdos_file_write_kmem (struct inode * emd_dir,
-				struct file * filp,
+ssize_t umsdos_file_write_kmem (struct file *filp,
 				const char *buf,
-				size_t count,
-				loff_t * offs)
+				size_t count)
 {
 	int ret;
-	struct dentry *old_dentry;
-
 
 	Printk ((KERN_DEBUG " STARTED WRITE_KMEM /mn/\n"));
-	Printk ((KERN_DEBUG "  using emd=%ld\n", emd_dir->i_ino));
-
-	old_dentry = filp->f_dentry;	/* save it */
-	filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir, NULL);
-
-	*offs = filp->f_pos;	/* FIXME, in read_kmem also: offs is not used so why pass it ?!!! /mn/ */
-
-	ret = umsdos_file_write_kmem_real (filp, buf, count, offs);
+	ret = umsdos_file_write_kmem_real (filp, buf, count);
 
+#warning Should d_drop be here ?
+#if 0
 	d_drop (filp->f_dentry);
-	filp->f_pos = *offs;
-	filp->f_dentry = old_dentry;
+#endif
 
 	return ret;
 }
@@ -182,24 +145,18 @@
  * Write a block of bytes into one EMD file.
  * The block of data is NOT in user space.
  * 
- * Return 0 if ok, a negative error code if not.
+ * Return 0 if OK, a negative error code if not.
  */
 
-ssize_t umsdos_emd_dir_write (	struct inode * emd_dir,
-				struct file * filp,
+ssize_t umsdos_emd_dir_write (	struct file *filp,
 				char *buf,	/* buffer in kernel memory, not in user space */
-				size_t count,
-				loff_t * offs)
+				size_t count)
 {
 	int written;
-	loff_t myofs = 0;
 
 #ifdef __BIG_ENDIAN
 	struct umsdos_dirent *d = (struct umsdos_dirent *) buf;
 
-#endif
-	filp->f_flags = 0;
-#ifdef __BIG_ENDIAN
 	d->nlink = cpu_to_le16 (d->nlink);
 	d->uid = cpu_to_le16 (d->uid);
 	d->gid = cpu_to_le16 (d->gid);
@@ -210,13 +167,10 @@
 	d->mode = cpu_to_le16 (d->mode);
 #endif
 
-	if (offs)
-		myofs = *offs;	/* if offs is not NULL, read it */
-	Printk (("umsdos_emd_dir_write /mn/: calling write_kmem with %p, %p, %p, %d, %Ld\n", emd_dir, filp, buf, count, myofs));
-	written = umsdos_file_write_kmem (emd_dir, filp, buf, count, &myofs);
+	filp->f_flags = 0;
+	Printk (("umsdos_emd_dir_write /mn/: calling write_kmem with %p, %p, %d, %Ld\n", filp, buf, count, filp->f_pos));
+	written = umsdos_file_write_kmem (filp, buf, count);
 	Printk (("umsdos_emd_dir_write /mn/: write_kmem returned\n"));
-	if (offs)
-		*offs = myofs;	/* if offs is not NULL, store myofs there */
 
 #ifdef __BIG_ENDIAN
 	d->nlink = le16_to_cpu (d->nlink);
@@ -229,29 +183,27 @@
 	d->mode = le16_to_cpu (d->mode);
 #endif
 
-#if 1
+#if UMS_DEBUG
 	if (written != count)
 		Printk ((KERN_ERR "umsdos_emd_dir_write: ERROR: written (%d) != count (%d)\n", written, count));
 #endif
 
+
 	return written != count ? -EIO : 0;
 }
 
 
 
 /*
- *    Read a block of bytes from one EMD file.
+ *      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.
+ *      Return 0 if OK, -EIO if any error.
  */
 
-ssize_t umsdos_emd_dir_read (struct inode * emd_dir,
-			     struct file * filp,
+ssize_t umsdos_emd_dir_read (struct file *filp,
 			     char *buf,		/* buffer in kernel memory, not in user space */
-			     size_t count,
-			     loff_t * offs)
+			     size_t count)
 {
-	loff_t myofs = 0;
 	long int ret = 0;
 	int sizeread;
 
@@ -261,12 +213,10 @@
 
 #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, &myofs);
+	sizeread = umsdos_file_read_kmem (filp, buf, count);
 	if (sizeread != count) {
-		printk ("UMSDOS: problem with EMD file. Can't read pos = %Ld (%d != %d)\n", filp->f_pos, sizeread, count);
+		printk ("UMSDOS:  problem with EMD file:  can't read pos = %Ld (%d != %d)\n", filp->f_pos, sizeread, count);
 		ret = -EIO;
 	}
 #ifdef __BIG_ENDIAN
@@ -279,42 +229,88 @@
 	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;
 
 }
 
 
 
+/*
+ * this checks weather filp points to directory or file,
+ * and if directory, it assumes that it has not yet been
+ * converted to point to EMD_FILE, and fixes it
+ *
+ * calling code should save old filp->f_dentry, call fix_emd_filp
+ * and if it succeeds (return code 0), do fin_dentry (filp->f_dentry)
+ * when it is over. It should also restore old filp->f_dentry.
+ *
+ */
+
+int fix_emd_filp (struct file *filp)
+{
+	struct inode *dir=filp->f_dentry->d_inode;
+	struct inode *emd_dir;
+  
+	/* is current file (which should be EMD or directory) EMD? */
+	if (dir->u.umsdos_i.i_emd_owner == 0xffffffff) {
+		dget (filp->f_dentry);
+		Printk ((KERN_WARNING "\nfix_emd_filp: EMD already done (should not be !)\n\n"));
+		return 0;
+	}
+	/* it is not, we need to make it so */
+	
+	emd_dir = umsdos_emd_dir_lookup (dir, 0);
+	if (emd_dir == NULL) {
+		Printk ((KERN_ERR "\nfix_emd_filp: EMD not found (should never happen)!!!\n\n"));
+		return -99;
+	}
+  
+	filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir, filp->f_dentry);	/* filp->f_dentry is dir containing EMD file, so it IS the parent dentry... */
+
+	return 0;
+}
+
 
 /*
- * Locate the EMD file in a directory .
+ * Locate the EMD file in a directory.
  * 
- * Return NULL if error. If ok, dir->u.umsdos_i.emd_inode 
+ * Return NULL if error, dir->u.umsdos_i.emd_inode if OK. 
+ * caller must iput() returned inode when finished with it!
  */
 
 struct inode *umsdos_emd_dir_lookup (struct inode *dir, int creat)
 {
 	struct inode *ret = NULL;
-	int res;
+	struct dentry *d_dir=NULL, *dlook=NULL;
+	int rv;
 
 	Printk ((KERN_DEBUG "Entering umsdos_emd_dir_lookup\n"));
+	if (!dir) printk (KERN_CRIT "umsdos FATAL: should never happen: dir=NULL!\n");
+	check_inode (dir);
+	
 	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));
+		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 %.*s -", UMSDOS_EMD_NAMELEN, UMSDOS_EMD_FILE));
-		res = compat_umsdos_real_lookup (dir, UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, &ret);
-		PRINTK ((KERN_DEBUG "-returned %d\n", res));
+
+		d_dir = geti_dentry (dir);
+		dlook = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, d_dir);
+		rv = umsdos_real_lookup (dir, dlook);
+		
+		PRINTK ((KERN_DEBUG "-returned %d\n", rv));
 		Printk ((KERN_INFO "emd_dir_lookup "));
-		if (ret != NULL) {
+		
+		ret = dlook->d_inode;
+		if (ret) {
 			Printk (("Found --linux "));
 			dir->u.umsdos_i.i_emd_dir = ret->i_ino;
+			inc_count (ret);	/* we'll need the inode */
+			fin_dentry (dlook);	/* but not dentry */
+			check_inode (ret);
 		} else if (creat) {
 			int code;
-
+			
 			Printk ((" * ERROR * /mn/: creat not yet implemented? not fixed? "));
 			Printk (("avant create "));
 			inc_count (dir);
@@ -330,14 +326,15 @@
 				printk (KERN_WARNING "UMSDOS: Can't create EMD file\n");
 			}
 		}
+		
 		if (ret != NULL) {
 			/* Disable UMSDOS_notify_change() for EMD file */
+			/* inc_count (ret); // we need to return with incremented inode. FIXME: didn't umsdos_real_lookup already did that? and compat_msdos_create ? */
 			ret->u.umsdos_i.i_emd_owner = 0xffffffff;
 		}
-		
 	}
 
-#if 1
+#if UMS_DEBUG
 	Printk ((KERN_DEBUG "umsdos_emd_dir_lookup returning %p /mn/\n", ret));
 	if (ret != NULL)
 		Printk ((KERN_DEBUG " returning ino=%lu\n", ret->i_ino));
@@ -350,7 +347,7 @@
 /*
  * creates an EMD file
  * 
- * Return NULL if error. If ok, dir->u.umsdos_i.emd_inode 
+ * Return NULL if error, dir->u.umsdos_i.emd_inode if OK. 
  */
 
 struct inode *umsdos_emd_dir_create (struct inode *dir, struct dentry *dentry, int mode)
@@ -387,30 +384,33 @@
 /*
  * Read an entry from the EMD file.
  * Support variable length record.
- * Return -EIO if error, 0 if ok.
+ * Return -EIO if error, 0 if OK.
+ *
+ * does not change {d,i}_count
  */
 
-int umsdos_emd_dir_readentry (
-				     struct inode *emd_dir,
-				     struct file *filp,
+int umsdos_emd_dir_readentry (	     struct file *filp,
 				     struct umsdos_dirent *entry)
 {
 	int ret;
 
 	Printk ((KERN_DEBUG "umsdos_emd_dir_readentry /mn/: entering.\n"));
-	Printk (("umsdos_emd_dir_readentry /mn/: trying to lookup %.*s (ino=%lu) using EMD %lu\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name, filp->f_dentry->d_inode->i_ino, emd_dir->i_ino));
+	Printk (("umsdos_emd_dir_readentry /mn/: reading EMD %.*s (ino=%lu) at pos=%d\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name, filp->f_dentry->d_inode->i_ino, (int) filp->f_pos));
 
-	ret = umsdos_emd_dir_read (emd_dir, filp, (char *) entry, UMSDOS_REC_SIZE, NULL);
-	if (ret == 0) {		/* note /mn/: is this wrong? ret is always 0 or -EIO. but who knows. It used to work this way... */
+	ret = umsdos_emd_dir_read (filp, (char *) entry, UMSDOS_REC_SIZE);
+	if (ret == 0) {	/* if no error */
 		/* 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, NULL);
+			Printk ((KERN_DEBUG "umsdos_emd_dir_readentry /mn/: %d > %d!\n", recsize, UMSDOS_REC_SIZE));
+			ret = umsdos_emd_dir_read (filp, ((char *) entry) + UMSDOS_REC_SIZE, recsize - UMSDOS_REC_SIZE);
 		}
 	}
-	Printk (("umsdos_emd_dir_readentry /mn/: returning %d.\n", ret));
+	Printk (("umsdos_emd_dir_readentry /mn/: ret=%d.\n", ret));
+	if (entry && ret == 0) {
+		Printk (("umsdos_emd_dir_readentry /mn/: returning len=%d,name=%.*s\n", (int) entry->name_len, (int) entry->name_len, entry->name));
+	}
 	return ret;
 }
 
@@ -419,16 +419,15 @@
 
 /*
  * Write an entry in the EMD file.
- * Return 0 if ok, -EIO if some error.
+ * Return 0 if OK, -EIO if some error.
  */
 
-int umsdos_writeentry (
-			      struct inode *dir,
+int umsdos_writeentry (	      struct inode *dir,
 			      struct inode *emd_dir,
 			      struct umsdos_info *info,
 			      int free_entry)
 
-{				/* This entry is deleted, so Write all 0's */
+{				/* This entry is deleted, so write all 0's. */
 	int ret = 0;
 	struct dentry *emd_dentry;
 	struct file filp;
@@ -438,11 +437,11 @@
 	fill_new_filp (&filp, NULL);
 
 	Printk (("umsdos_writeentry /mn/: entering...\n"));
-	emd_dentry = creat_dentry ("wremd_mn", 8, emd_dir, NULL);
+	emd_dentry = geti_dentry (emd_dir);
 
 	if (free_entry) {
 		/* #Specification: EMD file / empty entries
-		 * Unused entry in the EMD file are identify
+		 * Unused entry in the EMD file are identified
 		 * by the name_len field equal to 0. However to
 		 * help future extension (or bug correction :-( ),
 		 * empty entries are filled with 0.
@@ -453,26 +452,26 @@
 		memset (entry->name + entry->name_len, '\0', sizeof (entry->name) - entry->name_len);
 		/* #Specification: EMD file / spare bytes
 		 * 10 bytes are unused in each record of the EMD. They
-		 * are set to 0 all the time. So it will be possible
+		 * are set to 0 all the time, so it will be possible
 		 * to do new stuff and rely on the state of those
-		 * bytes in old EMD file around.
+		 * bytes in old EMD files.
 		 */
 		memset (entry->spare, 0, sizeof (entry->spare));
 	}
 	Printk (("umsdos_writeentry /mn/: if passed...\n"));
 
 	if (!info)
-		printk (KERN_ERR "umsdosfs: /mn/ info is empty ! ooops...\n");
+		printk (KERN_ERR "UMSDOS:  /mn/ info is empty!  Oops!\n");
 	filp.f_pos = info->f_pos;
 	filp.f_reada = 0;
 	filp.f_flags = O_RDWR;
 	filp.f_dentry = emd_dentry;
-	filp.f_op = &umsdos_file_operations;	/* /mn/ - we have to fill it with dummy values so we won't segfault */
+	filp.f_op = &umsdos_file_operations;	/* /mn/ - We have to fill it with dummy values so we won't segfault. */
 
-	ret = umsdos_emd_dir_write (emd_dir, &filp, (char *) entry, info->recsize, NULL);
+	ret = umsdos_emd_dir_write (&filp, (char *) entry, info->recsize);
 	Printk (("emd_dir_write returned with %d!\n", ret));
 	if (ret != 0) {
-		printk ("UMSDOS: problem with EMD file. Can't write\n");
+		printk ("UMSDOS:  problem with EMD file:  can't write\n");
 	} else {
 		dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 		/* dir->i_dirt = 1; FIXME iput/dput ??? */
@@ -500,7 +499,7 @@
  * Fill the read buffer and take care of the byte remaining inside.
  * Unread bytes are simply move to the beginning.
  * 
- * Return -ENOENT if EOF, 0 if ok, a negative error code if any problem.
+ * Return -ENOENT if EOF, 0 if OK, a negative error code if any problem.
  */
 
 static int umsdos_fillbuf (
@@ -511,6 +510,7 @@
 	int mustmove = buf->size - buf->pos;
 	int mustread;
 	int remain;
+	struct inode *old_ino;
 
 	PRINTK ((KERN_DEBUG "Entering umsdos_fillbuf, for inode %lu, buf=%p\n", inode->i_ino, buf));
 
@@ -523,7 +523,10 @@
 	if (remain < mustread)
 		mustread = remain;
 	if (mustread > 0) {
-		ret = umsdos_emd_dir_read (inode, &buf->filp, buf->buffer + mustmove, mustread, NULL);
+		old_ino = buf->filp.f_dentry->d_inode;	/* FIXME: do we need to save/restore it ? */
+		buf->filp.f_dentry->d_inode = inode;
+		ret = umsdos_emd_dir_read (&buf->filp, buf->buffer + mustmove, mustread);
+		buf->filp.f_dentry->d_inode = old_ino;
 		if (ret == 0)
 			buf->size = mustmove + mustread;
 	} else if (mustmove) {
@@ -555,43 +558,73 @@
  * 
  * All this to say that umsdos_writeentry must be call after this
  * function since it rely on the f_pos field of info.
+ *
+ * calling code is expected to iput() returned *pt_emd_dir
+ *
  */
 
-static int umsdos_find (
-			       struct inode *dir,
+static int umsdos_find (       struct inode *dir,
 			       struct umsdos_info *info,	/* Hold name and name_len */
 								/* Will hold the entry found */
 			       struct inode **pt_emd_dir)	/* Will hold the emd_dir inode or NULL if not found */
 
 {
 	/* #Specification: EMD file structure
-	 * The EMD file uses a fairly simple layout. It is made of records
-	 * (UMSDOS_REC_SIZE == 64). When a name can't be written is a single
-	 * record, multiple contiguous record are allocated.
+	 * The EMD file uses a fairly simple layout.  It is made of records
+	 * (UMSDOS_REC_SIZE == 64).  When a name can't be written in a single
+	 * record, multiple contiguous records are allocated.
 	 */
 	int ret = -ENOENT;
 	struct inode *emd_dir;
 	struct umsdos_dirent *entry = &info->entry;
 
 	Printk (("umsdos_find: locating %.*s in dir %lu\n", entry->name_len, entry->name, dir->i_ino));
+	check_inode (dir);
 
 	emd_dir = umsdos_emd_dir_lookup (dir, 1);
 	if (emd_dir != NULL) {
 		int recsize = info->recsize;
 		struct {
 			off_t posok;	/* Position available to store the entry */
-			int found;	/* A valid empty position has been found */
+			int found;	/* A valid empty position has been found. */
 			off_t one;	/* One empty position -> maybe <- large enough */
 			int onesize;	/* size of empty region starting at one */
 		} empty;
 
-		/* Read several entries at a time to speed up the search */
+		/* Read several entries at a time to speed up the search. */
 		struct find_buffer buf;
-		struct dentry *dentry;
+		struct dentry *demd;
 
-		dentry = creat_dentry ("umsfind-mn", 10, emd_dir, NULL);
-
-		fill_new_filp (&buf.filp, dentry);
+		Printk (("umsdos_find: check emd_dir...\n"));
+		check_inode (emd_dir);
+		
+#if 0		/* FIXME! not needed. but there are count wraps. somewhere before umsdos_find there should be inc_count/iput pair around umsdos_find call.... */
+		inc_count (emd_dir);	/* since we are going to fin_dentry, and need emd_dir afterwards -- caling code will iput() it */
+#endif		
+		demd = geti_dentry (emd_dir);
+		if (demd) {
+			dget (demd);	/* because we'll have to dput it */
+		} else {
+			/*
+			 * We don't have dentry alias for this inode. Too bad.
+			 * So we'll fake something (as best as we can).
+			 * (maybe we should do it in any case just to keep it simple?)
+			 *
+			 * Note that this is legal for EMD file, since in some places
+			 * we keep inode, but discard dentry (since we would have no way
+			 * to discard it later). Yes, this probably should be fixed somehow,
+			 * it is just that I don't have idea how right now, and I've spent
+			 * quite some time to track it down why it dies here. Maybe new emd_dir_lookup
+			 * which returns dentry ? hmmmm... FIXME...
+			 *
+			 */
+		 	Printk ((KERN_WARNING "umsdos_find: inode has no alias for EMD inode, fake it\n"));
+		 	demd = creat_dentry ("@emd_find@", 10, emd_dir, NULL);
+		}
+		
+		check_dentry_path (demd, " EMD_DIR_DENTRY umsdos_find");
+		
+		fill_new_filp (&buf.filp, demd);
 
 		buf.pos = 0;
 		buf.size = 0;
@@ -613,20 +646,20 @@
 				}
 			} else if (rentry->name_len == 0) {
 				/* We are looking for an empty section at least */
-				/* recsize large */
+				/* as large as recsize. */
 				if (entry->name_len == 0) {
 					info->f_pos = file_pos;
 					ret = 0;
 					break;
 				} else if (!empty.found) {
 					if (empty.onesize == 0) {
-						/* This is the first empty record of a section */
+						/* This is the first empty record of a section. */
 						empty.one = file_pos;
 					}
 					/* grow the empty section */
 					empty.onesize += UMSDOS_REC_SIZE;
 					if (empty.onesize == recsize) {
-						/* here is a large enough section */
+						/* Here is a large enough section. */
 						empty.posok = empty.one;
 						empty.found = 1;
 					}
@@ -643,10 +676,9 @@
 						break;
 					}
 				} else {
-					empty.onesize = 0;	/* Reset the free slot search */
+					empty.onesize = 0;	/* Reset the free slot search. */
 					if (entry->name_len == rentry->name_len
-					    && memcmp (entry->name, rentry->name, rentry->name_len)
-					    == 0) {
+					    && memcmp (entry->name, rentry->name, rentry->name_len) == 0) {
 						info->f_pos = file_pos;
 						*entry = *rentry;
 						ret = 0;
@@ -658,6 +690,7 @@
 			}
 		}
 		umsdos_manglename (info);
+		fin_dentry (demd);
 	}
 	*pt_emd_dir = emd_dir;
 
@@ -667,15 +700,14 @@
 
 
 /*
- * Add a new entry in the emd file
- * Return 0 if ok or a negative error code.
- * Return -EEXIST if the entry already exist.
+ * Add a new entry in the EMD file.
+ * Return 0 if OK or a negative error code.
+ * Return -EEXIST if the entry already exists.
  * 
  * Complete the information missing in info.
  */
 
-int umsdos_newentry (
-			    struct inode *dir,
+int umsdos_newentry (	    struct inode *dir,
 			    struct umsdos_info *info)
 {
 	struct inode *emd_dir;
@@ -687,18 +719,17 @@
 		ret = umsdos_writeentry (dir, emd_dir, info, 0);
 		Printk (("umsdos_writeentry EMD ret = %d\n", ret));
 	}
-	iput (emd_dir); /* FIXME? */
+	iput (emd_dir);
 	return ret;
 }
 
 
 /*
  * Create a new hidden link.
- * Return 0 if ok, an error code if not.
+ * Return 0 if OK, an error code if not.
  */
 
-int umsdos_newhidden (
-			     struct inode *dir,
+int umsdos_newhidden (	     struct inode *dir,
 			     struct umsdos_info *info)
 {
 	struct inode *emd_dir;
@@ -707,28 +738,26 @@
 	umsdos_parse ("..LINK", 6, info);
 	info->entry.name_len = 0;
 	ret = umsdos_find (dir, info, &emd_dir);
-	iput (emd_dir); /* FIXME? */
+	iput (emd_dir);
 	if (ret == -ENOENT || ret == 0) {
 		/* #Specification: hard link / hidden name
 		 * When a hard link is created, the original file is renamed
 		 * to a hidden name. The name is "..LINKNNN" where NNN is a
 		 * number define from the entry offset in the EMD file.
 		 */
-		info->entry.name_len = sprintf (info->entry.name, "..LINK%ld"
-						,info->f_pos);
+		info->entry.name_len = sprintf (info->entry.name, "..LINK%ld", info->f_pos);
 		ret = 0;
 	}
 	return ret;
 }
 /*
- * Remove an entry from the emd file
- * Return 0 if ok, a negative error code otherwise.
+ * Remove an entry from the EMD file.
+ * Return 0 if OK, a negative error code otherwise.
  * 
  * Complete the information missing in info.
  */
 
-int umsdos_delentry (
-			    struct inode *dir,
+int umsdos_delentry (	    struct inode *dir,
 			    struct umsdos_info *info,
 			    int isdir)
 {
@@ -748,38 +777,41 @@
 			}
 		}
 	}
-	iput(emd_dir); /* FIXME? */
+	iput (emd_dir);
 	return ret;
 }
 
 
 /*
- * Verify is a EMD directory is empty.
- * Return 0 if not empty
- * 1 if empty
- * 2 if empty, no EMD file.
+ * Verify that a EMD directory is empty. Return 
+ * 0 if not empty,
+ * 1 if empty,
+ * 2 if empty or no EMD file.
  */
 
 int umsdos_isempty (struct inode *dir)
 {
-	struct dentry *dentry;
+	struct dentry *dentry, *d_dir;
 
 	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 the EMD file does not exist, it is certainly empty. :-) */
 	if (emd_dir != NULL) {
 		struct file filp;
 
-		dentry = creat_dentry ("isempty-mn", 10, dir, NULL);
+		d_dir = geti_dentry (dir);
+		dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir, d_dir);
+		check_dentry_path (dentry, "umsdos_isempty BEGIN");
 		fill_new_filp (&filp, dentry);
+		filp.f_pos = 0;
 		filp.f_flags = O_RDONLY;
 
 		ret = 1;
 		while (filp.f_pos < emd_dir->i_size) {
 			struct umsdos_dirent entry;
 
-			if (umsdos_emd_dir_readentry (emd_dir, &filp, &entry) != 0) {
+			if (umsdos_emd_dir_readentry (&filp, &entry) != 0) {
 				ret = 0;
 				break;
 			} else if (entry.name_len != 0) {
@@ -787,24 +819,28 @@
 				break;
 			}
 		}
-		iput (emd_dir); /* FIXME? */
+		fin_dentry (dentry);
+		check_dentry_path (dentry, "umsdos_isempty END");
+		iput (emd_dir);
 	}
 	return ret;
 }
 
 /*
  * Locate an entry in a EMD directory.
- * Return 0 if ok, errcod if not, generally -ENOENT.
+ * Return 0 if OK, error code if not, generally -ENOENT.
+ *
+ * does not change i_count
  */
 
-int umsdos_findentry (
-			     struct inode *dir,
+int umsdos_findentry (	     struct inode *dir,
 			     struct umsdos_info *info,
 			     int expect)
-{				/* 0: anything */
-	/* 1: file */
-	/* 2: directory */
-	struct inode *emd_dir;
+				/* 0: anything */
+				/* 1: file */
+				/* 2: directory */
+{		
+	struct inode *emd_dir=NULL;
 	int ret = umsdos_find (dir, info, &emd_dir);
 
 	if (ret == 0) {
@@ -817,7 +853,7 @@
 			}
 		}
 	}
-	iput (emd_dir); /* FIXME? */
+	iput (emd_dir);
 	Printk (("umsdos_findentry: returning %d\n", ret));
 	return ret;
 }

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