BIG 1:the "rewind code" in yaffs_readdir may cause dead loop reading
operation in NFSv3 readdir/readdirplus rpc all.
The "rewind code " in function "yaffs_readdir " is as following:
/* If the directory has changed since the open or last call to
readdir, rewind to after the 2 canned entries. */
if (f->f_version !=
inode->i_version) {
offset =
2;
f->f_pos =
offset;
f->f_version =
inode->i_version;
}
When export YAFFS as the nfs server, the fd will be re-opened in NFSv3
server callback :nfsd3_proc_readdirplus->nfsd_readdir->nfsd_open.
If the fd has been re-opened,the version of the fd recorded in f->f_version will be lost.The rewind code
will always rewind the f->f_pos to 2, this will replace the offset in nfs
file handle.
For example,when the nfs client requests a getdents system
call, and the dirent which be read contains so many child that nfs needs to call
readdirplus rpc all more than once, after the first readdir rpc call the offset
of the fd will be passed back to server,and according to the offset, the server
calls a second readdir rpc all, the server supposes that it reads the
dirent starting at the offset.If the inode->version has been changed during
the first rpc call,the "rewind code" will always rewind the offset, so the
error occurs.
I suggest that we may remove the "rewind code" because it is not
necessary .
BUG 2:yaffs_readdir "yaffs_gross_unlock(dev)" before filldir may cause concurrent protection
problem.
yaffs_readdir will unlock before filldir
callback.The filldir callback may calls
yaffs_lookup.
yaffs_lookup has following code segment at beginning
of the function:
if
(current != yaffs_dev_to_lc(dev)->readdir_process)
yaffs_gross_lock(dev);
This code is not concurrency safe.If there is more
than one thread call
yaffs_readdir,the yaffs_dev_to_lc(dev)->readdir_process can be changed by another thread after the first yaffs_readdir thread
“yaffs_gross_unlock(dev)" before filldir.
I suggest that not unlock before filldir in
yaffs_readdir, also need to change the usage of lock in
yaffs_lookup.