Re: [Yaffs] YAFFS readdir rewind causing endless listings

Top Pagina
Bijlagen:
Bericht als e-mail
+ (text/plain)
Delete this message
Reply to this message
Auteur: Andrew McKay
Datum:  
Aan: Rong Shen
CC: yaffs
Onderwerp: Re: [Yaffs] YAFFS readdir rewind causing endless listings
> While I was debugging my issue posted in "a bug regarding when space
> running out - shown in example",
> I managed to narrow it down to the same issue described here. I'm
> using 2.4.30 kernel with the latest Yaffs2
> cvs check out, hopefully my discussion will still apply here.


I have a newer kernel, and your patch won't compile with it, so I have a couple
of quick questions.

>
> My tracing showed the endless loop is caused by,


Good job tracing and understanding that. I was heading down that road, but got
lost along the way. I don't have enough understanding of Linux file systems to
feel confident making changes like this. But I thought that there could be a
similar solution to this.

> 1. busybox calls to readdir()


...

> 4. default_llseek() sets file->f_version to ++event, which causes it
> no longer same as inode->i_version, which
> then hits Todd's patch in yaffs_readdir() and causes yaffs_readdir()
> to list the directory files from the beginning,
> over and over again.


My default_llseek() sets file->f_version to 0. I guess this changed with newer
kernels?

> This issue only happens if the listed directory has too many files to
> be returned in one yaffs_readdir() call.


> So here comes my proposal to solve the endless listing issue, It's
> actually pretty simple - define a llssek() on directory
> operation. What I did for my 2.4 kernel was just copying
> generic_file_llseek(), deleting the line changing f_version, and
> pasting
> the rest to yaffs_fs.c, shown below.


Seems to make sense.


> Comments?


Since your patch doesn't compile for newer kernels, I'll attach my patch for a
2.6.20.4 Kernel. Exactly same method of fixing it as yours. I've tested it and
not found any issues with it. I'm going to the kernel on some of the other
developers systems and see how it works out there.

retrieving revision 1.1.8.1.24.1
diff -u -r1.1.8.1.24.1 yaffs_fs.c
--- yaffs_fs.c  5 Sep 2008 19:36:29 -0000       1.1.8.1.24.1
+++ yaffs_fs.c  13 Nov 2008 18:38:16 -0000
@@ -137,6 +137,7 @@
  static int yaffs_sync_object(struct file *file, struct dentry *dentry,
                              int datasync);


+static loff_t yaffs_dir_llseek(struct file *file, loff_t offset, int origin);
static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir);

  #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
@@ -280,6 +281,7 @@
         .read = generic_read_dir,
         .readdir = yaffs_readdir,
         .fsync = yaffs_sync_object,
+       .llseek = yaffs_dir_llseek,
  };


  static struct super_operations yaffs_super_ops = {
@@ -910,6 +912,29 @@
         return nWritten == 0 ? -ENOSPC : nWritten;
  }


+static loff_t yaffs_dir_llseek(struct file *file, loff_t offset, int origin)
+{
+       long long retval;
+
+       lock_kernel();
+       switch (origin) {
+               case 2:
+                       offset += i_size_read(file->f_path.dentry->d_inode);
+                       break;
+               case 1:
+                       offset += file->f_pos;
+       }
+       retval = -EINVAL;
+       if (offset >= 0) {
+               if (offset != file->f_pos) {
+                       file->f_pos = offset;
+               }
+               retval = offset;
+       }
+       unlock_kernel();
+       return retval;
+}
+
  static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
  {
         yaffs_Object *obj;




Andrew