On Fri, Nov 14, 2008 at 5:43 AM, Andrew McKay wrote: >> 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. Yes, my patch is for 2.4 kernels. > >> >> 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? > In the later kernels, they seem to have got rid of the global event variable, or maybe use for other purpose. But the idea of tracking directory changes with f_version and i_version should remain the same. >> 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. Nice to here it also works for you. Thanks. > 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 > Rong